From 00c6940851b362da0d86f155269ef27a94d234c5 Mon Sep 17 00:00:00 2001 From: Steve Ruiz Date: Mon, 11 Oct 2021 19:11:26 +0100 Subject: [PATCH] fix: freehand points (#4031) Co-authored-by: dwelle --- package.json | 3 +- src/components/App.tsx | 11 +++---- src/element/collision.ts | 12 ++++---- src/renderer/renderElement.ts | 4 +-- .../regressionTests.test.tsx.snap | 30 +++++++++++++++---- yarn.lock | 13 +++++--- 6 files changed, 49 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 56bbe007..9c2dadac 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@sentry/integrations": "6.2.5", "@testing-library/jest-dom": "5.11.10", "@testing-library/react": "11.2.6", + "@tldraw/vec": "0.0.106", "@types/jest": "26.0.22", "@types/react": "17.0.3", "@types/react-dom": "17.0.3", @@ -35,7 +36,7 @@ "nanoid": "3.1.22", "open-color": "1.8.0", "pako": "1.0.11", - "perfect-freehand": "1.0.6", + "perfect-freehand": "1.0.15", "png-chunk-text": "1.0.0", "png-chunks-encode": "1.0.0", "png-chunks-extract": "1.0.0", diff --git a/src/components/App.tsx b/src/components/App.tsx index 436f45ec..41f4f43b 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -686,7 +686,7 @@ class App extends React.Component { if (initialData?.libraryItems) { this.libraryItemsFromStorage = initialData.libraryItems; } - } catch (error) { + } catch (error: any) { console.error(error); initialData = { appState: { @@ -1400,7 +1400,7 @@ class App extends React.Component { await webShareTargetCache.delete("shared-file"); window.history.replaceState(null, APP_NAME, window.location.pathname); } - } catch (error) { + } catch (error: any) { this.setState({ errorMessage: error.message }); } }; @@ -3494,6 +3494,7 @@ class App extends React.Component { mutateElement(draggingElement, { points: [...points, [dx, dy]], pressures, + lastCommittedPoint: [dx, dy], }); this.actionManager.executeAction(actionFinalize); @@ -3839,7 +3840,7 @@ class App extends React.Component { // but can be safely ignored on older releases. const item = event.dataTransfer.items[0]; (file as any).handle = await (item as any).getAsFileSystemHandle(); - } catch (error) { + } catch (error: any) { console.warn(error.name, error.message); } } @@ -3859,7 +3860,7 @@ class App extends React.Component { }); return; } - } catch (error) { + } catch (error: any) { return this.setState({ isLoading: false, errorMessage: error.message, @@ -3899,7 +3900,7 @@ class App extends React.Component { // but can be safely ignored on older releases. const item = event.dataTransfer.items[0]; (file as any).handle = await (item as any).getAsFileSystemHandle(); - } catch (error) { + } catch (error: any) { console.warn(error.name, error.message); } } diff --git a/src/element/collision.ts b/src/element/collision.ts index ecf4092d..b94e8e7c 100644 --- a/src/element/collision.ts +++ b/src/element/collision.ts @@ -328,15 +328,15 @@ const hitTestFreeDrawElement = ( let P: readonly [number, number]; // For freedraw dots - if (element.points.length === 2) { - return ( - distance2d(A[0], A[1], x, y) < threshold || - distance2d(B[0], B[1], x, y) < threshold - ); + if ( + distance2d(A[0], A[1], x, y) < threshold || + distance2d(B[0], B[1], x, y) < threshold + ) { + return true; } // For freedraw lines - for (let i = 1; i < element.points.length - 1; i++) { + for (let i = 0; i < element.points.length; i++) { const delta = [B[0] - A[0], B[1] - A[1]]; const length = Math.hypot(delta[1], delta[0]); diff --git a/src/renderer/renderElement.ts b/src/renderer/renderElement.ts index c3dd3c75..124711e9 100644 --- a/src/renderer/renderElement.ts +++ b/src/renderer/renderElement.ts @@ -804,7 +804,7 @@ export function getFreeDrawSvgPath(element: ExcalidrawFreeDrawElement) { smoothing: 0.5, streamline: 0.5, easing: (t) => Math.sin((t * Math.PI) / 2), // https://easings.net/#easeOutSine - last: false, + last: !!element.lastCommittedPoint, // LastCommittedPoint is added on pointerup }; return getSvgPathFromStroke(getStroke(inputPoints as number[][], options)); @@ -839,5 +839,5 @@ function getSvgPathFromStroke(points: number[][]): string { ["M", points[0], "Q"], ) .join(" ") - .replaceAll(TO_FIXED_PRECISION, "$1"); + .replace(TO_FIXED_PRECISION, "$1"); } diff --git a/src/tests/__snapshots__/regressionTests.test.tsx.snap b/src/tests/__snapshots__/regressionTests.test.tsx.snap index 46ce9e99..010995b6 100644 --- a/src/tests/__snapshots__/regressionTests.test.tsx.snap +++ b/src/tests/__snapshots__/regressionTests.test.tsx.snap @@ -6707,7 +6707,10 @@ Object { "height": 10, "id": "id7", "isDeleted": false, - "lastCommittedPoint": null, + "lastCommittedPoint": Array [ + 50, + 10, + ], "opacity": 100, "points": Array [ Array [ @@ -8374,7 +8377,10 @@ Object { "height": 10, "id": "id7", "isDeleted": false, - "lastCommittedPoint": null, + "lastCommittedPoint": Array [ + 50, + 10, + ], "opacity": 100, "points": Array [ Array [ @@ -10533,7 +10539,10 @@ Object { "height": 10, "id": "id0", "isDeleted": false, - "lastCommittedPoint": null, + "lastCommittedPoint": Array [ + 10, + 10, + ], "opacity": 100, "points": Array [ Array [ @@ -10607,7 +10616,10 @@ Object { "height": 10, "id": "id0", "isDeleted": false, - "lastCommittedPoint": null, + "lastCommittedPoint": Array [ + 10, + 10, + ], "opacity": 100, "points": Array [ Array [ @@ -11637,7 +11649,10 @@ Object { "height": 10, "id": "id0", "isDeleted": false, - "lastCommittedPoint": null, + "lastCommittedPoint": Array [ + 10, + 10, + ], "opacity": 100, "points": Array [ Array [ @@ -11711,7 +11726,10 @@ Object { "height": 10, "id": "id0", "isDeleted": false, - "lastCommittedPoint": null, + "lastCommittedPoint": Array [ + 10, + 10, + ], "opacity": 100, "points": Array [ Array [ diff --git a/yarn.lock b/yarn.lock index 50dc75ca..ec210349 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1916,6 +1916,11 @@ "@babel/runtime" "^7.12.5" "@testing-library/dom" "^7.28.1" +"@tldraw/vec@0.0.106": + version "0.0.106" + resolved "https://registry.yarnpkg.com/@tldraw/vec/-/vec-0.0.106.tgz#34936176b314c7779a3ad897a07be7434cdbc655" + integrity sha512-sOI3/bEb0KbGTHb8s2lSnY+0uWEToehJXPjV9ItFEOPqRXKoKbWRUzN1OAP7AQa1FJA2/w/1oPO9Seycne6JRA== + "@tootallnate/once@1": version "1.1.2" resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz" @@ -9260,10 +9265,10 @@ pepjs@0.5.3: version "0.5.3" resolved "https://registry.npmjs.org/pepjs/-/pepjs-0.5.3.tgz" -perfect-freehand@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/perfect-freehand/-/perfect-freehand-1.0.6.tgz#feeb25450241f036ec13b43fa84bbb16f8e78e0f" - integrity sha512-wWkFwpgUirsfBDTb9nG6+VnFR0ge119QKU2Nu96vR4MHZMPGfOsQRD7cUk+9CK5P+TUmnrtX8yOEzUrQ6KHJoA== +perfect-freehand@1.0.15: + version "1.0.15" + resolved "https://registry.yarnpkg.com/perfect-freehand/-/perfect-freehand-1.0.15.tgz#d3e4769e0420c0d467c0147487a34793f0b421e7" + integrity sha512-uRglBAdRA/wzGTbI0F58fXOfNuDmUHq1S40u92d2oPGhO1YfEUGal7fT2g0N8gwkIwMD14ySeLroUVhs7aBBuw== performance-now@^2.1.0: version "2.1.0"