Skip to content

Commit

Permalink
Add taper: true (#47)
Browse files Browse the repository at this point in the history
* Add taper: true

* bump deps

* Update package.json

* Update deps
  • Loading branch information
steveruizok authored Jun 1, 2022
1 parent 385dac1 commit ff2500c
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 106 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,11 @@ The options object is optional, as are each of its properties.

The `start` and `end` options accept an object:

| Property | Type | Default | Description |
| -------- | -------- | ------- | ------------------------------------------- |
| `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. |
| Property | Type | Default | Description |
| -------- | ----------------- | ------- | ---------------------------------------------------------------------------------------- |
| `cap` | boolean | true | Whether to draw a cap. |
| `taper` | number or boolean | 0 | The distance to taper. If set to true, the taper will be the total length of the stroke. |
| `easing` | function | t => t | An easing function for the tapering effect. |

**Note:** The `cap` property has no effect when `taper` is more than zero.

Expand Down
4 changes: 0 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,13 @@
"@testing-library/react": "^12.0.0",
"@types/jest": "^27.0.1",
"@types/node": "^15.0.1",
"@types/react": "^17.0.19",
"@types/react-dom": "^17.0.9",
"@typescript-eslint/eslint-plugin": "^4.19.0",
"@typescript-eslint/parser": "^4.19.0",
"babel-jest": "^27.1.0",
"eslint": "^7.32.0",
"fake-indexeddb": "^3.1.3",
"jest": "^27.1.0",
"lerna": "^3.15.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"ts-jest": "^27.0.5",
"tslib": "^2.3.0",
"typedoc": "^0.21.9",
Expand Down
17 changes: 8 additions & 9 deletions packages/dev/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@
"files": [
"src"
],
"dependencies": {
"@types/react-dom": "^17.0.11"
},
"dependencies": {},
"devDependencies": {
"@modulz/radix-icons": "^4.0.0",
"@radix-ui/react-checkbox": "^0.1.0",
Expand All @@ -40,8 +38,8 @@
"@tldraw/intersect": "^0.1.3",
"@tldraw/vec": "^0.1.3",
"@types/node": "^14.14.35",
"@types/react": "^17.0.34",
"@types/react-dom": "^17.0.9",
"@types/react": "^18.0.10",
"@types/react-dom": "^18.0.5",
"concurrently": "6.0.1",
"create-serve": "1.0.1",
"css-tree": "^1.1.3",
Expand All @@ -50,12 +48,13 @@
"husky": "^7.0.0",
"jest": "^27.0.6",
"perfect-freehand": "^1.0.16",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-hotkeys-hook": "^3.4.0",
"rimraf": "3.0.2",
"rko": "^0.5.25",
"tslib": "^2.3.1",
"typescript": "^4.3.5"
"typescript": "^4.3.5",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"zustand": "^4.0.0-rc.1"
}
}
}
2 changes: 1 addition & 1 deletion packages/dev/src/components/controls/controls.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

.inputs {
display: grid;
grid-template-columns: auto 1fr auto;
grid-template-columns: 96px 1fr auto;
grid-auto-rows: 32px;
align-items: center;
column-gap: 16px;
Expand Down
44 changes: 39 additions & 5 deletions packages/dev/src/components/controls/controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export function Controls() {
}, [])

const handleTaperStartChange = React.useCallback((v: number[]) => {
app.patchStyleForAllShapes({ taperStart: v[0] })
app.patchStyleForAllShapes({ taperStart: v[0] === 100 ? true : v[0] })
}, [])

const handleEasingStartChange = React.useCallback((easing: string) => {
Expand All @@ -120,7 +120,7 @@ export function Controls() {
}, [])

const handleTaperEndChange = React.useCallback((v: number[]) => {
app.patchStyleForAllShapes({ taperEnd: v[0] })
app.patchStyleForAllShapes({ taperEnd: v[0] === 100 ? true : v[0] })
}, [])

const handleEasingEndChange = React.useCallback((easing: string) => {
Expand Down Expand Up @@ -199,7 +199,7 @@ export function Controls() {
<Slider
name="Size"
value={[style.size]}
min={0}
min={1}
max={100}
step={1}
onDoubleClick={handleResetSize}
Expand Down Expand Up @@ -255,7 +255,24 @@ export function Controls() {
<hr />
<Slider
name="Taper Start"
value={[style.taperStart]}
value={[
Math.max(
0,
Math.min(
100,
style.taperStart === true
? 100
: style.taperStart === false
? 0
: style.taperStart
)
),
]}
label={
typeof style.taperStart === 'boolean'
? style.taperStart.toString()
: undefined
}
min={0}
max={100}
step={1}
Expand Down Expand Up @@ -289,14 +306,31 @@ export function Controls() {
<hr />
<Slider
name="Taper End"
value={[style.taperEnd]}
value={[
Math.max(
0,
Math.min(
100,
style.taperEnd === true
? 100
: style.taperEnd === false
? 0
: style.taperEnd
)
),
]}
min={0}
max={100}
step={1}
onDoubleClick={handleResetTaperEnd}
onValueChange={handleTaperEndChange}
onPointerDown={handleTaperEndChangeStart}
onPointerUp={handleStyleChangeComplete}
label={
typeof style.taperEnd === 'boolean'
? style.taperEnd.toString()
: undefined
}
/>
{style.taperEnd <= 0 && (
<Checkbox
Expand Down
24 changes: 15 additions & 9 deletions packages/dev/src/components/slider/slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface SliderProps extends SliderOwnProps {
onPointerDown: () => void
onPointerUp: () => void
onDoubleClick: () => void
label?: string
}

export function Slider({
Expand All @@ -24,6 +25,7 @@ export function Slider({
min,
max,
step,
label,
value = [0],
...props
}: SliderProps) {
Expand Down Expand Up @@ -60,15 +62,19 @@ export function Slider({
</Thumb>
))}
</Root>
<input
className={styles.numberInput}
type="number"
value={value[0]}
min={min}
max={max}
step={step}
onChange={handleValueChange}
/>
{label ? (
<span style={{ textAlign: 'right' }}>{label}</span>
) : (
<input
className={styles.numberInput}
type="number"
value={value[0]}
min={min}
max={max}
step={step}
onChange={handleValueChange}
/>
)}
</>
)
}
41 changes: 21 additions & 20 deletions packages/dev/src/state/shapes/draw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export class DrawUtil extends TLShapeUtil<T, E> {

rotatedCache = new WeakMap<T, number[][]>([])

strokeCache = new WeakMap<T['points'], number[][]>([])
strokeCache = new WeakMap<T, number[][]>([])

getShape = (props: Partial<T>): T => {
return Utils.deepMerge<T>(
Expand Down Expand Up @@ -85,25 +85,26 @@ export class DrawUtil extends TLShapeUtil<T, E> {

const simulatePressure = shape.points[2]?.[2] === 0.5

const outlinePoints = Utils.getFromCache(
this.strokeCache,
shape.points,
() =>
getStroke(shape.points, {
size,
thinning,
streamline,
easing: EASINGS[easing],
smoothing,
start: {
taper: taperStart,
cap: capStart,
easing: EASINGS[easingStart],
},
end: { taper: taperEnd, cap: capEnd, easing: EASINGS[easingEnd] },
simulatePressure,
last: isDone,
})
const outlinePoints = Utils.getFromCache(this.strokeCache, shape, () =>
getStroke(shape.points, {
size,
thinning,
streamline,
easing: EASINGS[easing],
smoothing,
start: {
taper: taperStart,
cap: capStart,
easing: EASINGS[easingStart],
},
end: {
taper: taperEnd,
cap: capEnd,
easing: EASINGS[easingEnd],
},
simulatePressure,
last: isDone,
})
)

const drawPathData = getSvgPathFromStroke(outlinePoints)
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/src/state/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ export class AppState extends StateManager<State> {
}

if (Utils.pointInBounds(pt, bounds)) {
const points = draw.strokeCache.get(shape.points)
const points = draw.strokeCache.get(shape)

if (
(points &&
Expand Down
4 changes: 2 additions & 2 deletions packages/dev/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ export interface DrawStyles {
thinning: number
streamline: number
smoothing: number
taperStart: number
taperEnd: number
taperStart: number | boolean
taperEnd: number | boolean
capStart: boolean
capEnd: boolean
easingStart: Easing
Expand Down
10 changes: 5 additions & 5 deletions packages/perfect-freehand/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,11 @@ The options object is optional, as are each of its properties.

The `start` and `end` options accept an object:

| Property | Type | Default | Description |
| -------- | -------- | ------- | ------------------------------------------- |
| `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. |
| Property | Type | Default | Description |
| -------- | ----------------- | ------- | ---------------------------------------------------------------------------------------- |
| `cap` | boolean | true | Whether to draw a cap. |
| `taper` | number or boolean | 0 | The distance to taper. If set to true, the taper will be the total length of the stroke. |
| `easing` | function | t => t | An easing function for the tapering effect. |

**Note:** The `cap` property has no effect when `taper` is more than zero.

Expand Down
28 changes: 18 additions & 10 deletions packages/perfect-freehand/src/getStrokeOutlinePoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,11 @@ export function getStrokeOutlinePoints(
last: isComplete = false,
} = options

const {
cap: capStart = true,
taper: taperStart = 0,
easing: taperStartEase = (t) => t * (2 - t),
} = start
let { cap: capStart = true, easing: taperStartEase = (t) => t * (2 - t) } =
start

const {
cap: capEnd = true,
taper: taperEnd = 0,
easing: taperEndEase = (t) => --t * t * t + 1,
} = end
let { cap: capEnd = true, easing: taperEndEase = (t) => --t * t * t + 1 } =
end

// We can't do anything with an empty array or a stroke with negative size.
if (points.length === 0 || size <= 0) {
Expand All @@ -72,6 +66,20 @@ export function getStrokeOutlinePoints(
// The total length of the line
const totalLength = points[points.length - 1].runningLength

const taperStart =
start.taper === false
? 0
: start.taper === true
? Math.max(size, totalLength)
: (start.taper as number)

const taperEnd =
end.taper === false
? 0
: end.taper === true
? Math.max(size, totalLength)
: (end.taper as number)

// The minimum allowed distance between points (squared)
const minDistance = Math.pow(size * smoothing, 2)

Expand Down
4 changes: 2 additions & 2 deletions packages/perfect-freehand/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ export interface StrokeOptions {
simulatePressure?: boolean
start?: {
cap?: boolean
taper?: number
taper?: number | boolean
easing?: (distance: number) => number
}
end?: {
cap?: boolean
taper?: number
taper?: number | boolean
easing?: (distance: number) => number
}
// Whether to handle the points as a completed stroke.
Expand Down
Loading

1 comment on commit ff2500c

@vercel
Copy link

@vercel vercel bot commented on ff2500c Jun 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.