UNPKG

tldraw

Version:

A tiny little drawing editor.

135 lines (134 loc) 4.28 kB
import { StateNode, applyRotationToSnapshotShapes, degreesToRadians, getRotationSnapshot, shortAngleDist, snapAngle } from "@tldraw/editor"; import { kickoutOccludedShapes } from "../selectHelpers.mjs"; import { CursorTypeMap } from "./PointingResizeHandle.mjs"; const ONE_DEGREE = Math.PI / 180; class Rotating extends StateNode { static id = "rotating"; snapshot = {}; info = {}; markId = ""; onEnter(info) { this.info = info; this.parent.setCurrentToolIdMask(info.onInteractionEnd); this.markId = this.editor.markHistoryStoppingPoint("rotate start"); const snapshot = getRotationSnapshot({ editor: this.editor, ids: this.editor.getSelectedShapeIds() }); if (!snapshot) return this.parent.transition("idle", this.info); this.snapshot = snapshot; const newSelectionRotation = this._getRotationFromPointerPosition({ snapToNearestDegree: false }); applyRotationToSnapshotShapes({ editor: this.editor, delta: this._getRotationFromPointerPosition({ snapToNearestDegree: false }), snapshot: this.snapshot, stage: "start" }); this.editor.setCursor({ type: CursorTypeMap[this.info.handle], rotation: newSelectionRotation + this.snapshot.initialShapesRotation }); } onExit() { this.editor.setCursor({ type: "default", rotation: 0 }); this.parent.setCurrentToolIdMask(void 0); this.snapshot = {}; } onPointerMove() { this.update(); } onKeyDown() { this.update(); } onKeyUp() { this.update(); } onPointerUp() { this.complete(); } onComplete() { this.complete(); } onCancel() { this.cancel(); } // --- update() { const newSelectionRotation = this._getRotationFromPointerPosition({ snapToNearestDegree: false }); applyRotationToSnapshotShapes({ editor: this.editor, delta: newSelectionRotation, snapshot: this.snapshot, stage: "update" }); this.editor.setCursor({ type: CursorTypeMap[this.info.handle], rotation: newSelectionRotation + this.snapshot.initialShapesRotation }); } cancel() { this.editor.bailToMark(this.markId); if (this.info.onInteractionEnd) { this.editor.setCurrentTool(this.info.onInteractionEnd, this.info); } else { this.parent.transition("idle", this.info); } } complete() { applyRotationToSnapshotShapes({ editor: this.editor, delta: this._getRotationFromPointerPosition({ snapToNearestDegree: true }), snapshot: this.snapshot, stage: "end" }); kickoutOccludedShapes( this.editor, this.snapshot.shapeSnapshots.map((s) => s.shape.id) ); if (this.info.onInteractionEnd) { this.editor.setCurrentTool(this.info.onInteractionEnd, this.info); } else { this.parent.transition("idle", this.info); } } _getRotationFromPointerPosition({ snapToNearestDegree }) { const selectionRotation = this.editor.getSelectionRotation(); const selectionBounds = this.editor.getSelectionRotatedPageBounds(); const { inputs: { shiftKey, currentPagePoint } } = this.editor; const { initialCursorAngle, initialShapesRotation } = this.snapshot; if (!selectionBounds) return initialShapesRotation; const selectionPageCenter = selectionBounds.center.clone().rotWith(selectionBounds.point, selectionRotation); const preSnapRotationDelta = selectionPageCenter.angle(currentPagePoint) - initialCursorAngle; let newSelectionRotation = initialShapesRotation + preSnapRotationDelta; if (shiftKey) { newSelectionRotation = snapAngle(newSelectionRotation, 24); } else if (snapToNearestDegree) { newSelectionRotation = Math.round(newSelectionRotation / ONE_DEGREE) * ONE_DEGREE; if (this.editor.getInstanceState().isCoarsePointer) { const snappedToRightAngle = snapAngle(newSelectionRotation, 4); const angleToRightAngle = shortAngleDist(newSelectionRotation, snappedToRightAngle); if (Math.abs(angleToRightAngle) < degreesToRadians(5)) { newSelectionRotation = snappedToRightAngle; } } } return newSelectionRotation - initialShapesRotation; } } export { Rotating }; //# sourceMappingURL=Rotating.mjs.map