|
|
@ -3,7 +3,7 @@ import {
|
|
|
|
ExcalidrawLinearElement,
|
|
|
|
ExcalidrawLinearElement,
|
|
|
|
ExcalidrawElement,
|
|
|
|
ExcalidrawElement,
|
|
|
|
} from "./types";
|
|
|
|
} from "./types";
|
|
|
|
import { distance2d, rotate, isPathALoop } from "../math";
|
|
|
|
import { distance2d, rotate, isPathALoop, getGridPoint } from "../math";
|
|
|
|
import { getElementAbsoluteCoords } from ".";
|
|
|
|
import { getElementAbsoluteCoords } from ".";
|
|
|
|
import { getElementPointsCoords } from "./bounds";
|
|
|
|
import { getElementPointsCoords } from "./bounds";
|
|
|
|
import { Point, AppState } from "../types";
|
|
|
|
import { Point, AppState } from "../types";
|
|
|
@ -20,6 +20,7 @@ export class LinearElementEditor {
|
|
|
|
/** whether you're dragging a point */
|
|
|
|
/** whether you're dragging a point */
|
|
|
|
public isDragging: boolean;
|
|
|
|
public isDragging: boolean;
|
|
|
|
public lastUncommittedPoint: Point | null;
|
|
|
|
public lastUncommittedPoint: Point | null;
|
|
|
|
|
|
|
|
public pointerOffset: { x: number; y: number };
|
|
|
|
|
|
|
|
|
|
|
|
constructor(element: NonDeleted<ExcalidrawLinearElement>, scene: Scene) {
|
|
|
|
constructor(element: NonDeleted<ExcalidrawLinearElement>, scene: Scene) {
|
|
|
|
this.elementId = element.id as string & {
|
|
|
|
this.elementId = element.id as string & {
|
|
|
@ -31,6 +32,7 @@ export class LinearElementEditor {
|
|
|
|
this.activePointIndex = null;
|
|
|
|
this.activePointIndex = null;
|
|
|
|
this.lastUncommittedPoint = null;
|
|
|
|
this.lastUncommittedPoint = null;
|
|
|
|
this.isDragging = false;
|
|
|
|
this.isDragging = false;
|
|
|
|
|
|
|
|
this.pointerOffset = { x: 0, y: 0 };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
@ -57,8 +59,6 @@ export class LinearElementEditor {
|
|
|
|
setState: React.Component<any, AppState>["setState"],
|
|
|
|
setState: React.Component<any, AppState>["setState"],
|
|
|
|
scenePointerX: number,
|
|
|
|
scenePointerX: number,
|
|
|
|
scenePointerY: number,
|
|
|
|
scenePointerY: number,
|
|
|
|
lastX: number,
|
|
|
|
|
|
|
|
lastY: number,
|
|
|
|
|
|
|
|
): boolean {
|
|
|
|
): boolean {
|
|
|
|
if (!appState.editingLinearElement) {
|
|
|
|
if (!appState.editingLinearElement) {
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
@ -80,18 +80,14 @@ export class LinearElementEditor {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const [deltaX, deltaY] = rotate(
|
|
|
|
|
|
|
|
scenePointerX - lastX,
|
|
|
|
const newPoint = LinearElementEditor.createPointAt(
|
|
|
|
scenePointerY - lastY,
|
|
|
|
element,
|
|
|
|
0,
|
|
|
|
scenePointerX - editingLinearElement.pointerOffset.x,
|
|
|
|
0,
|
|
|
|
scenePointerY - editingLinearElement.pointerOffset.y,
|
|
|
|
-element.angle,
|
|
|
|
appState.gridSize,
|
|
|
|
);
|
|
|
|
);
|
|
|
|
const targetPoint = element.points[activePointIndex];
|
|
|
|
LinearElementEditor.movePoint(element, activePointIndex, newPoint);
|
|
|
|
LinearElementEditor.movePoint(element, activePointIndex, [
|
|
|
|
|
|
|
|
targetPoint[0] + deltaX,
|
|
|
|
|
|
|
|
targetPoint[1] + deltaY,
|
|
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
@ -120,14 +116,12 @@ export class LinearElementEditor {
|
|
|
|
: element.points[0],
|
|
|
|
: element.points[0],
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (isDragging) {
|
|
|
|
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
...editingLinearElement,
|
|
|
|
...editingLinearElement,
|
|
|
|
isDragging: false,
|
|
|
|
isDragging: false,
|
|
|
|
|
|
|
|
pointerOffset: { x: 0, y: 0 },
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return editingLinearElement;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static handlePointerDown(
|
|
|
|
static handlePointerDown(
|
|
|
|
event: React.PointerEvent<HTMLCanvasElement>,
|
|
|
|
event: React.PointerEvent<HTMLCanvasElement>,
|
|
|
@ -165,6 +159,7 @@ export class LinearElementEditor {
|
|
|
|
element,
|
|
|
|
element,
|
|
|
|
scenePointerX,
|
|
|
|
scenePointerX,
|
|
|
|
scenePointerY,
|
|
|
|
scenePointerY,
|
|
|
|
|
|
|
|
appState.gridSize,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
],
|
|
|
|
});
|
|
|
|
});
|
|
|
@ -194,10 +189,29 @@ export class LinearElementEditor {
|
|
|
|
ret.hitElement = element;
|
|
|
|
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({
|
|
|
|
setState({
|
|
|
|
editingLinearElement: {
|
|
|
|
editingLinearElement: {
|
|
|
|
...appState.editingLinearElement,
|
|
|
|
...appState.editingLinearElement,
|
|
|
|
activePointIndex: clickedPointIndex > -1 ? clickedPointIndex : null,
|
|
|
|
activePointIndex: clickedPointIndex > -1 ? clickedPointIndex : null,
|
|
|
|
|
|
|
|
pointerOffset: targetPoint
|
|
|
|
|
|
|
|
? {
|
|
|
|
|
|
|
|
x: scenePointerX - targetPoint[0],
|
|
|
|
|
|
|
|
y: scenePointerY - targetPoint[1],
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
: { x: 0, y: 0 },
|
|
|
|
},
|
|
|
|
},
|
|
|
|
});
|
|
|
|
});
|
|
|
|
return ret;
|
|
|
|
return ret;
|
|
|
@ -208,6 +222,7 @@ export class LinearElementEditor {
|
|
|
|
scenePointerX: number,
|
|
|
|
scenePointerX: number,
|
|
|
|
scenePointerY: number,
|
|
|
|
scenePointerY: number,
|
|
|
|
editingLinearElement: LinearElementEditor,
|
|
|
|
editingLinearElement: LinearElementEditor,
|
|
|
|
|
|
|
|
gridSize: number | null,
|
|
|
|
): LinearElementEditor {
|
|
|
|
): LinearElementEditor {
|
|
|
|
const { elementId, lastUncommittedPoint } = editingLinearElement;
|
|
|
|
const { elementId, lastUncommittedPoint } = editingLinearElement;
|
|
|
|
const element = LinearElementEditor.getElement(elementId);
|
|
|
|
const element = LinearElementEditor.getElement(elementId);
|
|
|
@ -227,8 +242,9 @@ export class LinearElementEditor {
|
|
|
|
|
|
|
|
|
|
|
|
const newPoint = LinearElementEditor.createPointAt(
|
|
|
|
const newPoint = LinearElementEditor.createPointAt(
|
|
|
|
element,
|
|
|
|
element,
|
|
|
|
scenePointerX,
|
|
|
|
scenePointerX - editingLinearElement.pointerOffset.x,
|
|
|
|
scenePointerY,
|
|
|
|
scenePointerY - editingLinearElement.pointerOffset.y,
|
|
|
|
|
|
|
|
gridSize,
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (lastPoint === lastUncommittedPoint) {
|
|
|
|
if (lastPoint === lastUncommittedPoint) {
|
|
|
@ -288,13 +304,15 @@ export class LinearElementEditor {
|
|
|
|
element: NonDeleted<ExcalidrawLinearElement>,
|
|
|
|
element: NonDeleted<ExcalidrawLinearElement>,
|
|
|
|
scenePointerX: number,
|
|
|
|
scenePointerX: number,
|
|
|
|
scenePointerY: number,
|
|
|
|
scenePointerY: number,
|
|
|
|
|
|
|
|
gridSize: number | null,
|
|
|
|
): Point {
|
|
|
|
): Point {
|
|
|
|
|
|
|
|
const pointerOnGrid = getGridPoint(scenePointerX, scenePointerY, gridSize);
|
|
|
|
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
|
|
|
const [x1, y1, x2, y2] = getElementAbsoluteCoords(element);
|
|
|
|
const cx = (x1 + x2) / 2;
|
|
|
|
const cx = (x1 + x2) / 2;
|
|
|
|
const cy = (y1 + y2) / 2;
|
|
|
|
const cy = (y1 + y2) / 2;
|
|
|
|
const [rotatedX, rotatedY] = rotate(
|
|
|
|
const [rotatedX, rotatedY] = rotate(
|
|
|
|
scenePointerX,
|
|
|
|
pointerOnGrid[0],
|
|
|
|
scenePointerY,
|
|
|
|
pointerOnGrid[1],
|
|
|
|
cx,
|
|
|
|
cx,
|
|
|
|
cy,
|
|
|
|
cy,
|
|
|
|
-element.angle,
|
|
|
|
-element.angle,
|
|
|
|