From 818821c293db914aa6e4a542ea0cf3cbc7f31d8a Mon Sep 17 00:00:00 2001 From: Daishi Kato Date: Fri, 31 Jul 2020 00:09:51 +0900 Subject: [PATCH] feat: grid mode for line editing (#1984) --- src/components/App.tsx | 3 +- src/element/linearElementEditor.ts | 68 +++++++++++++++++++----------- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/src/components/App.tsx b/src/components/App.tsx index 04338a8e..5af3abff 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -1883,6 +1883,7 @@ class App extends React.Component { scenePointerX, scenePointerY, this.state.editingLinearElement, + this.state.gridSize, ); if (editingLinearElement !== this.state.editingLinearElement) { this.setState({ editingLinearElement }); @@ -2778,8 +2779,6 @@ class App extends React.Component { (appState) => this.setState(appState), x, y, - pointerDownState.lastCoords.x, - pointerDownState.lastCoords.y, ); if (didDrag) { diff --git a/src/element/linearElementEditor.ts b/src/element/linearElementEditor.ts index 4b93aa44..468d2053 100644 --- a/src/element/linearElementEditor.ts +++ b/src/element/linearElementEditor.ts @@ -3,7 +3,7 @@ import { ExcalidrawLinearElement, ExcalidrawElement, } from "./types"; -import { distance2d, rotate, isPathALoop } from "../math"; +import { distance2d, rotate, isPathALoop, getGridPoint } from "../math"; import { getElementAbsoluteCoords } from "."; import { getElementPointsCoords } from "./bounds"; import { Point, AppState } from "../types"; @@ -20,6 +20,7 @@ export class LinearElementEditor { /** whether you're dragging a point */ public isDragging: boolean; public lastUncommittedPoint: Point | null; + public pointerOffset: { x: number; y: number }; constructor(element: NonDeleted, scene: Scene) { this.elementId = element.id as string & { @@ -31,6 +32,7 @@ export class LinearElementEditor { this.activePointIndex = null; this.lastUncommittedPoint = null; this.isDragging = false; + this.pointerOffset = { x: 0, y: 0 }; } // --------------------------------------------------------------------------- @@ -57,8 +59,6 @@ export class LinearElementEditor { setState: React.Component["setState"], scenePointerX: number, scenePointerY: number, - lastX: number, - lastY: number, ): boolean { if (!appState.editingLinearElement) { return false; @@ -80,18 +80,14 @@ export class LinearElementEditor { }, }); } - const [deltaX, deltaY] = rotate( - scenePointerX - lastX, - scenePointerY - lastY, - 0, - 0, - -element.angle, + + const newPoint = LinearElementEditor.createPointAt( + element, + scenePointerX - editingLinearElement.pointerOffset.x, + scenePointerY - editingLinearElement.pointerOffset.y, + appState.gridSize, ); - const targetPoint = element.points[activePointIndex]; - LinearElementEditor.movePoint(element, activePointIndex, [ - targetPoint[0] + deltaX, - targetPoint[1] + deltaY, - ]); + LinearElementEditor.movePoint(element, activePointIndex, newPoint); return true; } return false; @@ -120,13 +116,11 @@ export class LinearElementEditor { : element.points[0], ); } - if (isDragging) { - return { - ...editingLinearElement, - isDragging: false, - }; - } - return editingLinearElement; + return { + ...editingLinearElement, + isDragging: false, + pointerOffset: { x: 0, y: 0 }, + }; } static handlePointerDown( @@ -165,6 +159,7 @@ export class LinearElementEditor { element, scenePointerX, scenePointerY, + appState.gridSize, ), ], }); @@ -194,10 +189,29 @@ export class LinearElementEditor { ret.hitElement = element; } + const [x1, y1, x2, y2] = getElementAbsoluteCoords(element); + const cx = (x1 + x2) / 2; + const cy = (y1 + y2) / 2; + const targetPoint = + clickedPointIndex > -1 && + rotate( + element.x + element.points[clickedPointIndex][0], + element.y + element.points[clickedPointIndex][1], + cx, + cy, + element.angle, + ); + setState({ editingLinearElement: { ...appState.editingLinearElement, activePointIndex: clickedPointIndex > -1 ? clickedPointIndex : null, + pointerOffset: targetPoint + ? { + x: scenePointerX - targetPoint[0], + y: scenePointerY - targetPoint[1], + } + : { x: 0, y: 0 }, }, }); return ret; @@ -208,6 +222,7 @@ export class LinearElementEditor { scenePointerX: number, scenePointerY: number, editingLinearElement: LinearElementEditor, + gridSize: number | null, ): LinearElementEditor { const { elementId, lastUncommittedPoint } = editingLinearElement; const element = LinearElementEditor.getElement(elementId); @@ -227,8 +242,9 @@ export class LinearElementEditor { const newPoint = LinearElementEditor.createPointAt( element, - scenePointerX, - scenePointerY, + scenePointerX - editingLinearElement.pointerOffset.x, + scenePointerY - editingLinearElement.pointerOffset.y, + gridSize, ); if (lastPoint === lastUncommittedPoint) { @@ -288,13 +304,15 @@ export class LinearElementEditor { element: NonDeleted, scenePointerX: number, scenePointerY: number, + gridSize: number | null, ): Point { + const pointerOnGrid = getGridPoint(scenePointerX, scenePointerY, gridSize); const [x1, y1, x2, y2] = getElementAbsoluteCoords(element); const cx = (x1 + x2) / 2; const cy = (y1 + y2) / 2; const [rotatedX, rotatedY] = rotate( - scenePointerX, - scenePointerY, + pointerOnGrid[0], + pointerOnGrid[1], cx, cy, -element.angle,