Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

perfect-freehand

Package Overview
Dependencies
Maintainers
1
Versions
56
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

perfect-freehand - npm Package Compare versions

Comparing version 0.4.91 to 0.5.0

dist/cjs/index.js

72

package.json
{
"version": "0.4.91",
"version": "0.5.0",
"name": "perfect-freehand",
"private": false,
"description": "Draw perfect pressure-sensitive freehand strokes.",
"author": {

@@ -20,52 +22,28 @@ "name": "Steve Ruiz",

"license": "MIT",
"module": "dist/perfect-freehand.esm.js",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"files": [
"dist",
"src"
],
"engines": {
"node": ">=10"
},
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
"types": "./dist/types/index.d.ts",
"scripts": {
"start": "tsdx watch",
"build": "tsdx build",
"test": "tsdx test",
"lint": "tsdx lint",
"prepare": "tsdx build",
"size": "size-limit",
"analyze": "size-limit --why"
"start": "node scripts/dev & tsc --watch --incremental --emitDeclarationOnly --declarationMap --outDir dist/types",
"build": "yarn clean && node scripts/build && tsc --project tsconfig.build.json --emitDeclarationOnly --outDir dist/types",
"lint": "eslint src/ --ext .ts,.tsx",
"clean": "rm -rf dist",
"ts-node": "ts-node",
"docs": "typedoc --entryPoints src/index.ts"
},
"husky": {
"hooks": {
"pre-commit": "tsdx lint"
}
},
"prettier": {
"printWidth": 80,
"semi": false,
"singleQuote": true,
"trailingComma": "es5"
},
"size-limit": [
{
"path": "dist/perfect-freehand.cjs.production.min.js",
"limit": "10 KB"
},
{
"path": "dist/perfect-freehand.esm.js",
"limit": "10 KB"
}
],
"devDependencies": {
"@size-limit/preset-small-lib": "^4.9.2",
"husky": "^5.0.9",
"size-limit": "^4.9.2",
"tsdx": "^0.14.1",
"tslib": "^2.1.0",
"typescript": "^4.1.5"
"@types/jest": "^27.0.1",
"@types/node": "^15.0.1",
"@types/react": "^17.0.16",
"@types/react-dom": "^17.0.9",
"esbuild": "^0.12.21",
"eslint": "^7.22.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"ts-node": "^9.1.1",
"tslib": "^2.3.0",
"typedoc": "^0.20.35",
"typescript": "^4.3.5"
},
"peerDependencies": {},
"dependencies": {}
"gitHead": "285dece1681b7a21bffb9309fee476c5f44495f5"
}

@@ -68,6 +68,8 @@ # ![Screenshot](screenshot.svg 'Perfect Freehand')

| `easing` | function | t => t | An easing function to apply to each point's pressure. |
| `start` | function | t => t | Tapering options for the start of the line. |
| `start` | { } | | Tapering options for the start of the line. |
| `end` | { } | | Tapering options for the end of the line. |
| `last` | boolean | true | Whether the stroke is complete. |
| `last` | boolean | true | Whether the stroke is complete. |
**Note:** When the `last` property is `true`, the line's end will be drawn at the last input point, rather than slightly behind it.
The `start` and `end` options accept an object:

@@ -77,6 +79,7 @@

| -------- | -------- | ------- | ------------------------------------------- |
| `taper` | boolean | 0 | The distance to taper. |
| `easing` | function | t => | An easing function for the tapering effect. |
| `cap` | boolean | true | Whether to draw a cap. |
| `taper` | number | 0 | The distance to taper. |
| `easing` | function | t => t | An easing function for the tapering effect. |
When `taper` is zero for either start or end, the library will add a rounded cap at that end of the line.
**Note:** The `cap` property has no effect when `taper` is more than zero.

@@ -89,3 +92,3 @@ ```js

streamline: 0.5,
easing: t => t * t * t,
easing: (t) => t * t * t,
simulatePressure: true,

@@ -95,7 +98,7 @@ last: true,

taper: 20,
easing: t => t * t * t,
easing: (t) => t * t * t,
},
end: {
taper: 20,
easing: t => t * t * t,
easing: (t) => t * t * t,
},

@@ -117,3 +120,3 @@ })

function getSvgPathFromStroke(stroke) {
if (!stroke.length) return ""
if (!stroke.length) return ''

@@ -126,7 +129,7 @@ const d = stroke.reduce(

},
["M", ...stroke[0], "Q"]
['M', ...stroke[0], 'Q']
)
d.push("Z")
return d.join(" ")
d.push('Z')
return d.join(' ')
}

@@ -138,3 +141,3 @@ ```

```js
import getStroke from "perfect-freehand"
import getStroke from 'perfect-freehand'

@@ -149,3 +152,3 @@ const myStroke = getStroke(myInputPoints)

```jsx
<path d={pathData}/>
<path d={pathData} />
```

@@ -187,5 +190,5 @@

```jsx
import * as React from "react"
import getStroke from "perfect-freehand"
import { getSvgPathFromStroke } from "./utils"
import * as React from 'react'
import getStroke from 'perfect-freehand'
import { getSvgPathFromStroke } from './utils'

@@ -211,3 +214,3 @@ export default function Example() {

onPointerMove={handlePointerMove}
style={{ touchAction: "none" }}
style={{ touchAction: 'none' }}
>

@@ -221,3 +224,3 @@ {points && (

smoothing: 0.5,
streamline: 0.5
streamline: 0.5,
})

@@ -224,0 +227,0 @@ )}

import { toPointsArray, getStrokeRadius } from './utils'
import { StrokeOptions, StrokePoint } from './types'
import type { StrokeOptions, StrokePoint } from './types'
import * as vec from './vec'

@@ -18,18 +18,13 @@

>(points: (T | K)[], options = {} as StrokeOptions): StrokePoint[] {
let { simulatePressure = true, streamline = 0.5, size = 8 } = options
let { streamline = 0.5 } = options
const { simulatePressure = true } = options
streamline /= 2
streamline = streamline / (simulatePressure ? 4 : 2)
if (!simulatePressure) {
streamline /= 2
}
const pts = toPointsArray(points)
let len = pts.length
if (pts.length === 0) return []
if (len === 0) return []
if (pts.length === 1) pts.push([...vec.add(pts[0], [1, 1]), pts[0][2]])
if (len === 1) pts.push(vec.add(pts[0], [1, 0]))
const strokePoints: StrokePoint[] = [

@@ -47,3 +42,3 @@ {

let i = 1, j = 0, curr = pts[i], prev = strokePoints[j];
i < len;
i < pts.length;
i++, curr = pts[i], prev = strokePoints[j]

@@ -55,15 +50,16 @@ ) {

const pressure = curr[2]
const vector = vec.uni(vec.vec(point, prev.point))
const vector = vec.uni(vec.sub(prev.point, point))
const distance = vec.dist(point, prev.point)
const runningLength = prev.runningLength + distance
strokePoints.push({
const strokePoint = {
point,
pressure,
pressure: curr[2],
vector,
distance,
runningLength,
})
}
strokePoints.push(strokePoint)
j += 1 // only increment j if we add an item to strokePoints

@@ -83,16 +79,16 @@ }

// Update the length to the length of the strokePoints array.
len = strokePoints.length
// const len = strokePoints.length
const totalLength = strokePoints[len - 1].runningLength
// const totalLength = strokePoints[len - 1].runningLength
for (let i = len - 2; i > 1; i--) {
const { runningLength, vector } = strokePoints[i]
const dpr = vec.dpr(strokePoints[i - 1].vector, strokePoints[i].vector)
if (totalLength - runningLength > size / 2 || dpr < 0.8) {
for (let j = i; j < len; j++) {
strokePoints[j].vector = vector
}
break
}
}
// for (let i = len - 2; i > 1; i--) {
// const { runningLength, vector } = strokePoints[i]
// const dpr = vec.dpr(strokePoints[i - 1].vector, strokePoints[i].vector)
// if (totalLength - runningLength > size / 2 || dpr < 0.8) {
// for (let j = i; j < len; j++) {
// strokePoints[j].vector = vector
// }
// break
// }
// }

@@ -125,3 +121,3 @@ return strokePoints

simulatePressure = true,
easing = t => t,
easing = (t) => t,
start = {},

@@ -137,9 +133,11 @@ end = {},

const {
cap: capStart = true,
taper: taperStart = 0,
easing: taperStartEase = t => t * (2 - t),
easing: taperStartEase = (t) => t * (2 - t),
} = start
const {
cap: capEnd = true,
taper: taperEnd = 0,
easing: taperEndEase = t => --t * t * t + 1,
easing: taperEndEase = (t) => --t * t * t + 1,
} = end

@@ -168,2 +166,4 @@

let firstRadius: number | undefined = undefined
// Previous vector

@@ -180,2 +180,4 @@ let prevVector = points[0].vector

let short = true
/*

@@ -188,5 +190,12 @@ Find the outline's left and right points

for (let i = 1; i < len - 1; i++) {
let { point, pressure, vector, distance, runningLength } = points[i]
for (let i = 0; i < len - 1; i++) {
let { pressure } = points[i]
const { point, vector, distance, runningLength } = points[i]
if (i > 0 && short && runningLength < size / 2) {
continue
} else if (short) {
short = false
}
/*

@@ -212,2 +221,6 @@ Calculate the radius

if (firstRadius === undefined) {
firstRadius = radius
}
/*

@@ -231,3 +244,3 @@ Apply tapering

radius *= Math.min(ts, te)
radius = Math.max(0.01, radius * Math.min(ts, te))

@@ -262,2 +275,3 @@ /*

}
/*

@@ -278,5 +292,6 @@ Add regular points

const alwaysAdd = i === 1 || dpr < 0.25
const alwaysAdd = i < 2 || dpr < 0.25
const minDistance = Math.pow(
(runningLength > size ? size : size / 2) * smoothing,
Math.max((runningLength > size ? size : size / 2) * smoothing, 1),
2

@@ -311,3 +326,3 @@ )

const lastPoint = points[len - 1]
const isVeryShort = rightPts.length < 2 || leftPts.length < 2
const isVeryShort = short || rightPts.length < 2 || leftPts.length < 2

@@ -361,4 +376,5 @@ /*

const startCap: number[][] = []
const endCap: number[][] = []
if (!taperStart && !(taperEnd && isVeryShort)) {
if (leftPts.length > 1 && rightPts.length > 1) {
tr = rightPts[1]

@@ -373,18 +389,36 @@

if (!vec.isEqual(tr, tl)) {
const start = vec.sub(
firstPoint.point,
vec.mul(vec.uni(vec.vec(tr, tl)), vec.dist(tr, tl) / 2)
)
if (capStart || taperStart) {
if (!taperStart && !(taperEnd && isVeryShort)) {
if (!vec.isEqual(tr, tl)) {
const start = vec.sub(
firstPoint.point,
vec.mul(vec.uni(vec.vec(tr, tl)), vec.dist(tr, tl) / 2)
)
for (let t = 0, step = 0.2; t <= 1; t += step) {
startCap.push(vec.rotAround(start, firstPoint.point, PI * t))
for (let t = 0, step = 0.1; t <= 1; t += step) {
startCap.push(vec.rotAround(start, firstPoint.point, PI * t))
}
leftPts.shift()
rightPts.shift()
}
} else {
startCap.push(firstPoint.point)
}
} else {
if (!vec.isEqual(tr, tl)) {
const vector = vec.uni(vec.vec(tr, tl))
const dist = vec.dist(tr, tl) / 2
leftPts.shift()
rightPts.shift()
startCap.push(vec.sub(firstPoint.point, vec.mul(vector, dist * 0.95)))
startCap.push(vec.sub(firstPoint.point, vec.mul(vector, dist)))
startCap.push(vec.add(firstPoint.point, vec.mul(vector, dist)))
startCap.push(vec.add(firstPoint.point, vec.mul(vector, dist * 0.95)))
leftPts.shift()
rightPts.shift()
}
}
}
/*
/*
Draw an end cap

@@ -399,15 +433,27 @@

const endCap: number[][] = []
const lastLeft = leftPts[leftPts.length - 1]
const lastRight = rightPts[rightPts.length - 1]
const mid = vec.med(lastLeft, lastRight)
const last = options.last
? lastPoint.point
: vec.lrp(mid, lastPoint.point, 0.618)
const vector = vec.uni(vec.sub(last, mid))
if (!taperEnd && !(taperStart && isVeryShort)) {
const start = vec.sub(
lastPoint.point,
vec.mul(vec.per(lastPoint.vector), radius)
)
for (let t = 0, step = 0.1; t <= 1; t += step) {
endCap.push(vec.rotAround(start, lastPoint.point, PI * 3 * t))
if (capEnd || taperEnd) {
if (!taperEnd && !(taperStart && isVeryShort)) {
const start = vec.add(last, vec.mul(vec.per(vector), radius))
for (let t = 0, step = 0.15; t <= 1; t += step) {
endCap.push(vec.rotAround(start, last, PI * 3 * t))
}
} else {
endCap.push(last)
}
} else {
const justBefore = vec.lrp(mid, last, 0.95)
const r = radius * 0.95
endCap.push(vec.add(justBefore, vec.mul(vec.per(vector), r)))
endCap.push(vec.add(last, vec.mul(vec.per(vector), r)))
endCap.push(vec.sub(last, vec.mul(vec.per(vector), r)))
endCap.push(vec.sub(justBefore, vec.mul(vec.per(vector), r)))
}
} else {
endCap.push(lastPoint.point)
}

@@ -414,0 +460,0 @@

@@ -9,2 +9,3 @@ export interface StrokeOptions {

start?: {
cap?: boolean
taper?: number

@@ -14,2 +15,3 @@ easing?: (distance: number) => number

end?: {
cap?: boolean
taper?: number

@@ -16,0 +18,0 @@ easing?: (distance: number) => number

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc