@tsdraw/core 0.8.2 → 0.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +120 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +50 -24
- package/dist/index.d.ts +50 -24
- package/dist/index.js +118 -56
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -63,7 +63,6 @@ interface TsdrawSessionStateSnapshot {
|
|
|
63
63
|
x: number;
|
|
64
64
|
y: number;
|
|
65
65
|
zoom: number;
|
|
66
|
-
rotation?: number;
|
|
67
66
|
};
|
|
68
67
|
currentToolId: string;
|
|
69
68
|
drawStyle: {
|
|
@@ -150,8 +149,31 @@ declare class InputManager {
|
|
|
150
149
|
getInputs(): PointerInput;
|
|
151
150
|
}
|
|
152
151
|
|
|
152
|
+
interface Viewport {
|
|
153
|
+
x: number;
|
|
154
|
+
y: number;
|
|
155
|
+
zoom: number;
|
|
156
|
+
}
|
|
157
|
+
declare function createViewport(): Viewport;
|
|
158
|
+
declare function screenToPage(viewport: Viewport, screenX: number, screenY: number): {
|
|
159
|
+
x: number;
|
|
160
|
+
y: number;
|
|
161
|
+
};
|
|
162
|
+
declare function pageToScreen(viewport: Viewport, pageX: number, pageY: number): {
|
|
163
|
+
x: number;
|
|
164
|
+
y: number;
|
|
165
|
+
};
|
|
166
|
+
declare function setViewport(viewport: Viewport, updater: {
|
|
167
|
+
x?: number;
|
|
168
|
+
y?: number;
|
|
169
|
+
zoom?: number;
|
|
170
|
+
}): Viewport;
|
|
171
|
+
declare function panViewport(viewport: Viewport, dx: number, dy: number): Viewport;
|
|
172
|
+
declare function zoomViewport(viewport: Viewport, factor: number, centerX?: number, centerY?: number): Viewport;
|
|
173
|
+
|
|
153
174
|
interface IEditor {
|
|
154
175
|
getZoomLevel(): number;
|
|
176
|
+
readonly viewport: Viewport;
|
|
155
177
|
options: {
|
|
156
178
|
dragDistanceSquared: number;
|
|
157
179
|
};
|
|
@@ -181,15 +203,20 @@ interface IEditor {
|
|
|
181
203
|
fill: FillStyle;
|
|
182
204
|
size: SizeStyle;
|
|
183
205
|
}>): void;
|
|
206
|
+
setViewport(partial: Partial<Viewport>): void;
|
|
184
207
|
panBy(dx: number, dy: number): void;
|
|
185
208
|
}
|
|
186
209
|
|
|
187
210
|
interface ToolPointerDownInfo {
|
|
188
211
|
point: Vec3;
|
|
212
|
+
screenX?: number;
|
|
213
|
+
screenY?: number;
|
|
189
214
|
}
|
|
190
215
|
interface ToolPointerMoveInfo {
|
|
191
216
|
screenDeltaX?: number;
|
|
192
217
|
screenDeltaY?: number;
|
|
218
|
+
screenX?: number;
|
|
219
|
+
screenY?: number;
|
|
193
220
|
}
|
|
194
221
|
interface ToolKeyInfo {
|
|
195
222
|
key: string;
|
|
@@ -218,30 +245,26 @@ declare abstract class StateNode {
|
|
|
218
245
|
onInterrupt(): void;
|
|
219
246
|
}
|
|
220
247
|
|
|
221
|
-
interface
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
248
|
+
interface CameraPanSession {
|
|
249
|
+
initialViewportX: number;
|
|
250
|
+
initialViewportY: number;
|
|
251
|
+
originScreenX: number;
|
|
252
|
+
originScreenY: number;
|
|
253
|
+
velocityX: number;
|
|
254
|
+
velocityY: number;
|
|
255
|
+
previousScreenX: number;
|
|
256
|
+
previousScreenY: number;
|
|
257
|
+
lastMoveTime: number;
|
|
258
|
+
}
|
|
259
|
+
declare function beginCameraPan(viewport: Viewport, screenX: number, screenY: number): CameraPanSession;
|
|
260
|
+
declare function moveCameraPan(session: CameraPanSession, currentScreenX: number, currentScreenY: number): {
|
|
229
261
|
x: number;
|
|
230
262
|
y: number;
|
|
231
263
|
};
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
declare function setViewport(viewport: Viewport, updater: {
|
|
237
|
-
x?: number;
|
|
238
|
-
y?: number;
|
|
239
|
-
zoom?: number;
|
|
240
|
-
rotation?: number;
|
|
241
|
-
}): Viewport;
|
|
242
|
-
declare function panViewport(viewport: Viewport, dx: number, dy: number): Viewport;
|
|
243
|
-
declare function zoomViewport(viewport: Viewport, factor: number, centerX?: number, centerY?: number): Viewport;
|
|
244
|
-
declare function rotateViewport(viewport: Viewport, delta: number, centerX?: number, centerY?: number): Viewport;
|
|
264
|
+
interface CameraSlideAnimation {
|
|
265
|
+
stop: () => void;
|
|
266
|
+
}
|
|
267
|
+
declare function startCameraSlide(session: CameraPanSession, applyPan: (dx: number, dy: number) => void, onFrame: () => void): CameraSlideAnimation | null;
|
|
245
268
|
|
|
246
269
|
type TsdrawRenderTheme = 'light' | 'dark';
|
|
247
270
|
declare function resolveThemeColor(colorStyle: string, theme: TsdrawRenderTheme): string;
|
|
@@ -348,7 +371,6 @@ declare class Editor {
|
|
|
348
371
|
setViewport(partial: Partial<Viewport>): void;
|
|
349
372
|
panBy(dx: number, dy: number): void;
|
|
350
373
|
zoomAt(factor: number, screenX: number, screenY: number): void;
|
|
351
|
-
rotateAt(delta: number, screenX: number, screenY: number): void;
|
|
352
374
|
deleteShapes(ids: ShapeId[]): void;
|
|
353
375
|
getDocumentSnapshot(): TsdrawDocumentSnapshot;
|
|
354
376
|
loadDocumentSnapshot(snapshot: TsdrawDocumentSnapshot): void;
|
|
@@ -613,8 +635,12 @@ declare class HandIdleState extends StateNode {
|
|
|
613
635
|
|
|
614
636
|
declare class HandDraggingState extends StateNode {
|
|
615
637
|
static id: string;
|
|
638
|
+
private panSession;
|
|
639
|
+
onEnter(info?: ToolStateTransitionInfo): void;
|
|
616
640
|
onPointerMove(info?: ToolPointerMoveInfo): void;
|
|
641
|
+
getPanSession(): CameraPanSession | null;
|
|
617
642
|
onPointerUp(): void;
|
|
643
|
+
onExit(): void;
|
|
618
644
|
onCancel(): void;
|
|
619
645
|
onInterrupt(): void;
|
|
620
646
|
}
|
|
@@ -630,4 +656,4 @@ declare function decodePathToPoints(segments: {
|
|
|
630
656
|
y: number;
|
|
631
657
|
}[];
|
|
632
658
|
|
|
633
|
-
export { type Bounds, CanvasRenderer, CircleDrawingState, CircleIdleState, type ColorStyle, DEFAULT_COLORS, DRAG_DISTANCE_SQUARED, type DashStyle, type DefaultToolId, DocumentStore, type DocumentStoreSnapshot, type DrawSegment, type DrawShape, ERASER_MARGIN, Editor, type EditorOptions, EraserErasingState, EraserIdleState, EraserPointingState, type FillStyle, HandDraggingState, HandIdleState, type ICanvasRenderer, type IEditor, InputManager, MAX_POINTS_PER_SHAPE, type PageState, PenDrawingState, PenIdleState, type PointerInput, type ResizeHandle, STROKE_WIDTHS, type SegmentType, SelectIdleState, type SelectionBounds, type Shape, type ShapeId, type SizeStyle, SquareDrawingState, SquareIdleState, StateNode, type StateNodeConstructor, type ToolDefinition, type ToolId, type ToolKeyInfo, ToolManager, type ToolPointerDownInfo, type ToolPointerMoveInfo, type ToolStateContext, type ToolStateTransitionInfo, type TransformSnapshot, type TsdrawDocumentSnapshot, type TsdrawEditorSnapshot, type TsdrawHistorySnapshot, type TsdrawPageRecord, type TsdrawPersistedRecord, type TsdrawRenderTheme, type TsdrawSessionStateSnapshot, type TsdrawShapeRecord, type Vec3, type Viewport, applyMove, applyResize, applyRotation, boundsContainPoint, boundsIntersect, boundsOf, buildStartPositions, buildTransformSnapshots, closestOnSegment, createViewport, decodeFirstPoint, decodeLastPoint, decodePathToPoints, decodePoints, distance, documentSnapshotToRecords, encodePoints, getSelectionBoundsPage, getShapeBounds, getShapesInBounds, getTopShapeAtPoint, isSelectTool, minDistanceToPolyline, normalizeSelectionBounds, padBounds, pageToScreen, panViewport, pointHitsShape, recordsToDocumentSnapshot, resolveThemeColor, rotatePoint,
|
|
659
|
+
export { type Bounds, type CameraPanSession, type CameraSlideAnimation, CanvasRenderer, CircleDrawingState, CircleIdleState, type ColorStyle, DEFAULT_COLORS, DRAG_DISTANCE_SQUARED, type DashStyle, type DefaultToolId, DocumentStore, type DocumentStoreSnapshot, type DrawSegment, type DrawShape, ERASER_MARGIN, Editor, type EditorOptions, EraserErasingState, EraserIdleState, EraserPointingState, type FillStyle, HandDraggingState, HandIdleState, type ICanvasRenderer, type IEditor, InputManager, MAX_POINTS_PER_SHAPE, type PageState, PenDrawingState, PenIdleState, type PointerInput, type ResizeHandle, STROKE_WIDTHS, type SegmentType, SelectIdleState, type SelectionBounds, type Shape, type ShapeId, type SizeStyle, SquareDrawingState, SquareIdleState, StateNode, type StateNodeConstructor, type ToolDefinition, type ToolId, type ToolKeyInfo, ToolManager, type ToolPointerDownInfo, type ToolPointerMoveInfo, type ToolStateContext, type ToolStateTransitionInfo, type TransformSnapshot, type TsdrawDocumentSnapshot, type TsdrawEditorSnapshot, type TsdrawHistorySnapshot, type TsdrawPageRecord, type TsdrawPersistedRecord, type TsdrawRenderTheme, type TsdrawSessionStateSnapshot, type TsdrawShapeRecord, type Vec3, type Viewport, applyMove, applyResize, applyRotation, beginCameraPan, boundsContainPoint, boundsIntersect, boundsOf, buildStartPositions, buildTransformSnapshots, closestOnSegment, createViewport, decodeFirstPoint, decodeLastPoint, decodePathToPoints, decodePoints, distance, documentSnapshotToRecords, encodePoints, getSelectionBoundsPage, getShapeBounds, getShapesInBounds, getTopShapeAtPoint, isSelectTool, minDistanceToPolyline, moveCameraPan, normalizeSelectionBounds, padBounds, pageToScreen, panViewport, pointHitsShape, recordsToDocumentSnapshot, resolveThemeColor, rotatePoint, screenToPage, segmentHitsShape, segmentTouchesPolyline, setViewport, shapePagePoints, sqDistance, startCameraSlide, zoomViewport };
|
package/dist/index.d.ts
CHANGED
|
@@ -63,7 +63,6 @@ interface TsdrawSessionStateSnapshot {
|
|
|
63
63
|
x: number;
|
|
64
64
|
y: number;
|
|
65
65
|
zoom: number;
|
|
66
|
-
rotation?: number;
|
|
67
66
|
};
|
|
68
67
|
currentToolId: string;
|
|
69
68
|
drawStyle: {
|
|
@@ -150,8 +149,31 @@ declare class InputManager {
|
|
|
150
149
|
getInputs(): PointerInput;
|
|
151
150
|
}
|
|
152
151
|
|
|
152
|
+
interface Viewport {
|
|
153
|
+
x: number;
|
|
154
|
+
y: number;
|
|
155
|
+
zoom: number;
|
|
156
|
+
}
|
|
157
|
+
declare function createViewport(): Viewport;
|
|
158
|
+
declare function screenToPage(viewport: Viewport, screenX: number, screenY: number): {
|
|
159
|
+
x: number;
|
|
160
|
+
y: number;
|
|
161
|
+
};
|
|
162
|
+
declare function pageToScreen(viewport: Viewport, pageX: number, pageY: number): {
|
|
163
|
+
x: number;
|
|
164
|
+
y: number;
|
|
165
|
+
};
|
|
166
|
+
declare function setViewport(viewport: Viewport, updater: {
|
|
167
|
+
x?: number;
|
|
168
|
+
y?: number;
|
|
169
|
+
zoom?: number;
|
|
170
|
+
}): Viewport;
|
|
171
|
+
declare function panViewport(viewport: Viewport, dx: number, dy: number): Viewport;
|
|
172
|
+
declare function zoomViewport(viewport: Viewport, factor: number, centerX?: number, centerY?: number): Viewport;
|
|
173
|
+
|
|
153
174
|
interface IEditor {
|
|
154
175
|
getZoomLevel(): number;
|
|
176
|
+
readonly viewport: Viewport;
|
|
155
177
|
options: {
|
|
156
178
|
dragDistanceSquared: number;
|
|
157
179
|
};
|
|
@@ -181,15 +203,20 @@ interface IEditor {
|
|
|
181
203
|
fill: FillStyle;
|
|
182
204
|
size: SizeStyle;
|
|
183
205
|
}>): void;
|
|
206
|
+
setViewport(partial: Partial<Viewport>): void;
|
|
184
207
|
panBy(dx: number, dy: number): void;
|
|
185
208
|
}
|
|
186
209
|
|
|
187
210
|
interface ToolPointerDownInfo {
|
|
188
211
|
point: Vec3;
|
|
212
|
+
screenX?: number;
|
|
213
|
+
screenY?: number;
|
|
189
214
|
}
|
|
190
215
|
interface ToolPointerMoveInfo {
|
|
191
216
|
screenDeltaX?: number;
|
|
192
217
|
screenDeltaY?: number;
|
|
218
|
+
screenX?: number;
|
|
219
|
+
screenY?: number;
|
|
193
220
|
}
|
|
194
221
|
interface ToolKeyInfo {
|
|
195
222
|
key: string;
|
|
@@ -218,30 +245,26 @@ declare abstract class StateNode {
|
|
|
218
245
|
onInterrupt(): void;
|
|
219
246
|
}
|
|
220
247
|
|
|
221
|
-
interface
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
248
|
+
interface CameraPanSession {
|
|
249
|
+
initialViewportX: number;
|
|
250
|
+
initialViewportY: number;
|
|
251
|
+
originScreenX: number;
|
|
252
|
+
originScreenY: number;
|
|
253
|
+
velocityX: number;
|
|
254
|
+
velocityY: number;
|
|
255
|
+
previousScreenX: number;
|
|
256
|
+
previousScreenY: number;
|
|
257
|
+
lastMoveTime: number;
|
|
258
|
+
}
|
|
259
|
+
declare function beginCameraPan(viewport: Viewport, screenX: number, screenY: number): CameraPanSession;
|
|
260
|
+
declare function moveCameraPan(session: CameraPanSession, currentScreenX: number, currentScreenY: number): {
|
|
229
261
|
x: number;
|
|
230
262
|
y: number;
|
|
231
263
|
};
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
declare function setViewport(viewport: Viewport, updater: {
|
|
237
|
-
x?: number;
|
|
238
|
-
y?: number;
|
|
239
|
-
zoom?: number;
|
|
240
|
-
rotation?: number;
|
|
241
|
-
}): Viewport;
|
|
242
|
-
declare function panViewport(viewport: Viewport, dx: number, dy: number): Viewport;
|
|
243
|
-
declare function zoomViewport(viewport: Viewport, factor: number, centerX?: number, centerY?: number): Viewport;
|
|
244
|
-
declare function rotateViewport(viewport: Viewport, delta: number, centerX?: number, centerY?: number): Viewport;
|
|
264
|
+
interface CameraSlideAnimation {
|
|
265
|
+
stop: () => void;
|
|
266
|
+
}
|
|
267
|
+
declare function startCameraSlide(session: CameraPanSession, applyPan: (dx: number, dy: number) => void, onFrame: () => void): CameraSlideAnimation | null;
|
|
245
268
|
|
|
246
269
|
type TsdrawRenderTheme = 'light' | 'dark';
|
|
247
270
|
declare function resolveThemeColor(colorStyle: string, theme: TsdrawRenderTheme): string;
|
|
@@ -348,7 +371,6 @@ declare class Editor {
|
|
|
348
371
|
setViewport(partial: Partial<Viewport>): void;
|
|
349
372
|
panBy(dx: number, dy: number): void;
|
|
350
373
|
zoomAt(factor: number, screenX: number, screenY: number): void;
|
|
351
|
-
rotateAt(delta: number, screenX: number, screenY: number): void;
|
|
352
374
|
deleteShapes(ids: ShapeId[]): void;
|
|
353
375
|
getDocumentSnapshot(): TsdrawDocumentSnapshot;
|
|
354
376
|
loadDocumentSnapshot(snapshot: TsdrawDocumentSnapshot): void;
|
|
@@ -613,8 +635,12 @@ declare class HandIdleState extends StateNode {
|
|
|
613
635
|
|
|
614
636
|
declare class HandDraggingState extends StateNode {
|
|
615
637
|
static id: string;
|
|
638
|
+
private panSession;
|
|
639
|
+
onEnter(info?: ToolStateTransitionInfo): void;
|
|
616
640
|
onPointerMove(info?: ToolPointerMoveInfo): void;
|
|
641
|
+
getPanSession(): CameraPanSession | null;
|
|
617
642
|
onPointerUp(): void;
|
|
643
|
+
onExit(): void;
|
|
618
644
|
onCancel(): void;
|
|
619
645
|
onInterrupt(): void;
|
|
620
646
|
}
|
|
@@ -630,4 +656,4 @@ declare function decodePathToPoints(segments: {
|
|
|
630
656
|
y: number;
|
|
631
657
|
}[];
|
|
632
658
|
|
|
633
|
-
export { type Bounds, CanvasRenderer, CircleDrawingState, CircleIdleState, type ColorStyle, DEFAULT_COLORS, DRAG_DISTANCE_SQUARED, type DashStyle, type DefaultToolId, DocumentStore, type DocumentStoreSnapshot, type DrawSegment, type DrawShape, ERASER_MARGIN, Editor, type EditorOptions, EraserErasingState, EraserIdleState, EraserPointingState, type FillStyle, HandDraggingState, HandIdleState, type ICanvasRenderer, type IEditor, InputManager, MAX_POINTS_PER_SHAPE, type PageState, PenDrawingState, PenIdleState, type PointerInput, type ResizeHandle, STROKE_WIDTHS, type SegmentType, SelectIdleState, type SelectionBounds, type Shape, type ShapeId, type SizeStyle, SquareDrawingState, SquareIdleState, StateNode, type StateNodeConstructor, type ToolDefinition, type ToolId, type ToolKeyInfo, ToolManager, type ToolPointerDownInfo, type ToolPointerMoveInfo, type ToolStateContext, type ToolStateTransitionInfo, type TransformSnapshot, type TsdrawDocumentSnapshot, type TsdrawEditorSnapshot, type TsdrawHistorySnapshot, type TsdrawPageRecord, type TsdrawPersistedRecord, type TsdrawRenderTheme, type TsdrawSessionStateSnapshot, type TsdrawShapeRecord, type Vec3, type Viewport, applyMove, applyResize, applyRotation, boundsContainPoint, boundsIntersect, boundsOf, buildStartPositions, buildTransformSnapshots, closestOnSegment, createViewport, decodeFirstPoint, decodeLastPoint, decodePathToPoints, decodePoints, distance, documentSnapshotToRecords, encodePoints, getSelectionBoundsPage, getShapeBounds, getShapesInBounds, getTopShapeAtPoint, isSelectTool, minDistanceToPolyline, normalizeSelectionBounds, padBounds, pageToScreen, panViewport, pointHitsShape, recordsToDocumentSnapshot, resolveThemeColor, rotatePoint,
|
|
659
|
+
export { type Bounds, type CameraPanSession, type CameraSlideAnimation, CanvasRenderer, CircleDrawingState, CircleIdleState, type ColorStyle, DEFAULT_COLORS, DRAG_DISTANCE_SQUARED, type DashStyle, type DefaultToolId, DocumentStore, type DocumentStoreSnapshot, type DrawSegment, type DrawShape, ERASER_MARGIN, Editor, type EditorOptions, EraserErasingState, EraserIdleState, EraserPointingState, type FillStyle, HandDraggingState, HandIdleState, type ICanvasRenderer, type IEditor, InputManager, MAX_POINTS_PER_SHAPE, type PageState, PenDrawingState, PenIdleState, type PointerInput, type ResizeHandle, STROKE_WIDTHS, type SegmentType, SelectIdleState, type SelectionBounds, type Shape, type ShapeId, type SizeStyle, SquareDrawingState, SquareIdleState, StateNode, type StateNodeConstructor, type ToolDefinition, type ToolId, type ToolKeyInfo, ToolManager, type ToolPointerDownInfo, type ToolPointerMoveInfo, type ToolStateContext, type ToolStateTransitionInfo, type TransformSnapshot, type TsdrawDocumentSnapshot, type TsdrawEditorSnapshot, type TsdrawHistorySnapshot, type TsdrawPageRecord, type TsdrawPersistedRecord, type TsdrawRenderTheme, type TsdrawSessionStateSnapshot, type TsdrawShapeRecord, type Vec3, type Viewport, applyMove, applyResize, applyRotation, beginCameraPan, boundsContainPoint, boundsIntersect, boundsOf, buildStartPositions, buildTransformSnapshots, closestOnSegment, createViewport, decodeFirstPoint, decodeLastPoint, decodePathToPoints, decodePoints, distance, documentSnapshotToRecords, encodePoints, getSelectionBoundsPage, getShapeBounds, getShapesInBounds, getTopShapeAtPoint, isSelectTool, minDistanceToPolyline, moveCameraPan, normalizeSelectionBounds, padBounds, pageToScreen, panViewport, pointHitsShape, recordsToDocumentSnapshot, resolveThemeColor, rotatePoint, screenToPage, segmentHitsShape, segmentTouchesPolyline, setViewport, shapePagePoints, sqDistance, startCameraSlide, zoomViewport };
|
package/dist/index.js
CHANGED
|
@@ -223,34 +223,25 @@ var StateNode = class {
|
|
|
223
223
|
|
|
224
224
|
// src/canvas/viewport.ts
|
|
225
225
|
function createViewport() {
|
|
226
|
-
return { x: 0, y: 0, zoom: 1
|
|
226
|
+
return { x: 0, y: 0, zoom: 1 };
|
|
227
227
|
}
|
|
228
228
|
function screenToPage(viewport, screenX, screenY) {
|
|
229
|
-
const tx = screenX - viewport.x;
|
|
230
|
-
const ty = screenY - viewport.y;
|
|
231
|
-
const cos = Math.cos(viewport.rotation);
|
|
232
|
-
const sin = Math.sin(viewport.rotation);
|
|
233
229
|
return {
|
|
234
|
-
x: (
|
|
235
|
-
y: (-
|
|
230
|
+
x: (screenX - viewport.x) / viewport.zoom,
|
|
231
|
+
y: (screenY - viewport.y) / viewport.zoom
|
|
236
232
|
};
|
|
237
233
|
}
|
|
238
234
|
function pageToScreen(viewport, pageX, pageY) {
|
|
239
|
-
const scaledX = pageX * viewport.zoom;
|
|
240
|
-
const scaledY = pageY * viewport.zoom;
|
|
241
|
-
const cos = Math.cos(viewport.rotation);
|
|
242
|
-
const sin = Math.sin(viewport.rotation);
|
|
243
235
|
return {
|
|
244
|
-
x:
|
|
245
|
-
y:
|
|
236
|
+
x: pageX * viewport.zoom + viewport.x,
|
|
237
|
+
y: pageY * viewport.zoom + viewport.y
|
|
246
238
|
};
|
|
247
239
|
}
|
|
248
240
|
function setViewport(viewport, updater) {
|
|
249
241
|
return {
|
|
250
242
|
x: updater.x ?? viewport.x,
|
|
251
243
|
y: updater.y ?? viewport.y,
|
|
252
|
-
zoom: updater.zoom ?? viewport.zoom
|
|
253
|
-
rotation: updater.rotation ?? viewport.rotation
|
|
244
|
+
zoom: updater.zoom ?? viewport.zoom
|
|
254
245
|
};
|
|
255
246
|
}
|
|
256
247
|
function panViewport(viewport, dx, dy) {
|
|
@@ -262,23 +253,92 @@ function zoomViewport(viewport, factor, centerX, centerY) {
|
|
|
262
253
|
return { ...viewport, zoom };
|
|
263
254
|
}
|
|
264
255
|
const pageBefore = screenToPage(viewport, centerX, centerY);
|
|
265
|
-
const
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
256
|
+
const x = centerX - pageBefore.x * zoom;
|
|
257
|
+
const y = centerY - pageBefore.y * zoom;
|
|
258
|
+
return { x, y, zoom };
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// src/canvas/cameraPan.ts
|
|
262
|
+
var VELOCITY_LERP_FACTOR = 0.5;
|
|
263
|
+
var VELOCITY_ZERO_THRESHOLD = 0.01;
|
|
264
|
+
function beginCameraPan(viewport, screenX, screenY) {
|
|
265
|
+
return {
|
|
266
|
+
initialViewportX: viewport.x,
|
|
267
|
+
initialViewportY: viewport.y,
|
|
268
|
+
originScreenX: screenX,
|
|
269
|
+
originScreenY: screenY,
|
|
270
|
+
velocityX: 0,
|
|
271
|
+
velocityY: 0,
|
|
272
|
+
previousScreenX: screenX,
|
|
273
|
+
previousScreenY: screenY,
|
|
274
|
+
lastMoveTime: performance.now()
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
function moveCameraPan(session, currentScreenX, currentScreenY) {
|
|
278
|
+
const now = performance.now();
|
|
279
|
+
const elapsed = now - session.lastMoveTime;
|
|
280
|
+
if (elapsed > 0) {
|
|
281
|
+
const moveDx = currentScreenX - session.previousScreenX;
|
|
282
|
+
const moveDy = currentScreenY - session.previousScreenY;
|
|
283
|
+
const moveLen = Math.hypot(moveDx, moveDy);
|
|
284
|
+
if (moveLen > 0) {
|
|
285
|
+
const dirX = moveDx / moveLen;
|
|
286
|
+
const dirY = moveDy / moveLen;
|
|
287
|
+
const speed = moveLen / elapsed;
|
|
288
|
+
session.velocityX += (dirX * speed - session.velocityX) * VELOCITY_LERP_FACTOR;
|
|
289
|
+
session.velocityY += (dirY * speed - session.velocityY) * VELOCITY_LERP_FACTOR;
|
|
290
|
+
}
|
|
291
|
+
if (Math.abs(session.velocityX) < VELOCITY_ZERO_THRESHOLD) session.velocityX = 0;
|
|
292
|
+
if (Math.abs(session.velocityY) < VELOCITY_ZERO_THRESHOLD) session.velocityY = 0;
|
|
275
293
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
294
|
+
session.previousScreenX = currentScreenX;
|
|
295
|
+
session.previousScreenY = currentScreenY;
|
|
296
|
+
session.lastMoveTime = now;
|
|
297
|
+
return {
|
|
298
|
+
x: session.initialViewportX + (currentScreenX - session.originScreenX),
|
|
299
|
+
y: session.initialViewportY + (currentScreenY - session.originScreenY)
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
var SLIDE_FRICTION = 0.92;
|
|
303
|
+
var SLIDE_MIN_SPEED = 0.01;
|
|
304
|
+
var SLIDE_MAX_SPEED = 2;
|
|
305
|
+
var SLIDE_MIN_VELOCITY_TO_START = 0.1;
|
|
306
|
+
function startCameraSlide(session, applyPan, onFrame) {
|
|
307
|
+
const timeSinceLastMove = performance.now() - session.lastMoveTime;
|
|
308
|
+
const FRAME_DURATION = 16;
|
|
309
|
+
const decayFactor = Math.pow(1 - VELOCITY_LERP_FACTOR, timeSinceLastMove / FRAME_DURATION);
|
|
310
|
+
const effectiveVx = session.velocityX * decayFactor;
|
|
311
|
+
const effectiveVy = session.velocityY * decayFactor;
|
|
312
|
+
const speed = Math.hypot(effectiveVx, effectiveVy);
|
|
313
|
+
const clampedSpeed = Math.min(speed, SLIDE_MAX_SPEED);
|
|
314
|
+
if (clampedSpeed < SLIDE_MIN_VELOCITY_TO_START) return null;
|
|
315
|
+
const dirX = effectiveVx / speed;
|
|
316
|
+
const dirY = effectiveVy / speed;
|
|
317
|
+
let currentSpeed = clampedSpeed;
|
|
318
|
+
let lastTime = performance.now();
|
|
319
|
+
let rafId = 0;
|
|
320
|
+
const tick = () => {
|
|
321
|
+
const now = performance.now();
|
|
322
|
+
const elapsed = now - lastTime;
|
|
323
|
+
lastTime = now;
|
|
324
|
+
applyPan(dirX * currentSpeed * elapsed, dirY * currentSpeed * elapsed);
|
|
325
|
+
onFrame();
|
|
326
|
+
currentSpeed *= SLIDE_FRICTION;
|
|
327
|
+
if (currentSpeed < SLIDE_MIN_SPEED) {
|
|
328
|
+
rafId = 0;
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
rafId = requestAnimationFrame(tick);
|
|
332
|
+
};
|
|
333
|
+
rafId = requestAnimationFrame(tick);
|
|
334
|
+
return {
|
|
335
|
+
stop() {
|
|
336
|
+
if (rafId !== 0) {
|
|
337
|
+
cancelAnimationFrame(rafId);
|
|
338
|
+
rafId = 0;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
};
|
|
282
342
|
}
|
|
283
343
|
|
|
284
344
|
// src/utils/colors.ts
|
|
@@ -311,7 +371,6 @@ var CanvasRenderer = class {
|
|
|
311
371
|
render(ctx, viewport, shapes) {
|
|
312
372
|
ctx.save();
|
|
313
373
|
ctx.translate(viewport.x, viewport.y);
|
|
314
|
-
ctx.rotate(viewport.rotation);
|
|
315
374
|
ctx.scale(viewport.zoom, viewport.zoom);
|
|
316
375
|
for (const shape of shapes) {
|
|
317
376
|
if (shape.type === "draw") {
|
|
@@ -804,7 +863,7 @@ var PenDrawingState = class extends StateNode {
|
|
|
804
863
|
const z = this._startInfo?.point?.z ?? 0.5;
|
|
805
864
|
this._isPenDevice = penActive;
|
|
806
865
|
this._hasPressure = penActive || z !== 0.5;
|
|
807
|
-
const pressure = this._hasPressure ? toFixed(z) : 0.5;
|
|
866
|
+
const pressure = this._hasPressure ? toFixed(z * 1.25) : 0.5;
|
|
808
867
|
this._phase = inputs.getShiftKey() ? "straight" : "free";
|
|
809
868
|
this._extending = false;
|
|
810
869
|
this._lastSample = { ...origin };
|
|
@@ -901,13 +960,12 @@ var PenDrawingState = class extends StateNode {
|
|
|
901
960
|
const curPt = inputs.getCurrentPagePoint();
|
|
902
961
|
if (!this._hasPressure) {
|
|
903
962
|
const liveZ = curPt.z ?? 0.5;
|
|
904
|
-
if (liveZ !== 0.5 || inputs.getIsPen()) {
|
|
963
|
+
if (liveZ > 0 && liveZ !== 0.5 || inputs.getIsPen()) {
|
|
905
964
|
this._hasPressure = true;
|
|
906
|
-
this.editor.updateShapes([{ id, type: "draw", props: { isPen: true } }]);
|
|
907
965
|
}
|
|
908
966
|
}
|
|
909
967
|
const local = this.editor.getPointInShapeSpace(shape, curPt);
|
|
910
|
-
const pressure = this._hasPressure ? toFixed(curPt.z ?? 0.5) : 0.5;
|
|
968
|
+
const pressure = this._hasPressure ? toFixed((curPt.z ?? 0.5) * 1.25) : 0.5;
|
|
911
969
|
const pt = { x: toFixed(local.x), y: toFixed(local.y), z: pressure };
|
|
912
970
|
switch (this._phase) {
|
|
913
971
|
case "starting_straight": {
|
|
@@ -1053,7 +1111,7 @@ var PenDrawingState = class extends StateNode {
|
|
|
1053
1111
|
const firstPt = {
|
|
1054
1112
|
x: 0,
|
|
1055
1113
|
y: 0,
|
|
1056
|
-
z: this._hasPressure ? toFixed(curPage.z ?? 0.5) : 0.5
|
|
1114
|
+
z: this._hasPressure ? toFixed((curPage.z ?? 0.5) * 1.25) : 0.5
|
|
1057
1115
|
};
|
|
1058
1116
|
this._activePts = [firstPt];
|
|
1059
1117
|
this.editor.createShape({
|
|
@@ -1085,7 +1143,7 @@ var PenDrawingState = class extends StateNode {
|
|
|
1085
1143
|
endStroke() {
|
|
1086
1144
|
if (!this._target) return;
|
|
1087
1145
|
this.editor.updateShapes([
|
|
1088
|
-
{ id: this._target.id, type: "draw", props: { isComplete: true } }
|
|
1146
|
+
{ id: this._target.id, type: "draw", props: { isComplete: true, isPen: this._hasPressure } }
|
|
1089
1147
|
]);
|
|
1090
1148
|
this.ctx.transition("pen_idle");
|
|
1091
1149
|
}
|
|
@@ -1515,16 +1573,29 @@ var HandIdleState = class extends StateNode {
|
|
|
1515
1573
|
// src/tools/hand/states/HandDraggingState.ts
|
|
1516
1574
|
var HandDraggingState = class extends StateNode {
|
|
1517
1575
|
static id = "hand_dragging";
|
|
1576
|
+
panSession = null;
|
|
1577
|
+
onEnter(info) {
|
|
1578
|
+
const downInfo = info;
|
|
1579
|
+
const screenX = downInfo?.screenX ?? 0;
|
|
1580
|
+
const screenY = downInfo?.screenY ?? 0;
|
|
1581
|
+
this.panSession = beginCameraPan(this.editor.viewport, screenX, screenY);
|
|
1582
|
+
}
|
|
1518
1583
|
onPointerMove(info) {
|
|
1519
|
-
|
|
1520
|
-
const
|
|
1521
|
-
const
|
|
1522
|
-
|
|
1523
|
-
this.editor.
|
|
1584
|
+
if (!this.panSession) return;
|
|
1585
|
+
const screenX = info?.screenX ?? 0;
|
|
1586
|
+
const screenY = info?.screenY ?? 0;
|
|
1587
|
+
const target = moveCameraPan(this.panSession, screenX, screenY);
|
|
1588
|
+
this.editor.setViewport({ x: target.x, y: target.y });
|
|
1589
|
+
}
|
|
1590
|
+
getPanSession() {
|
|
1591
|
+
return this.panSession;
|
|
1524
1592
|
}
|
|
1525
1593
|
onPointerUp() {
|
|
1526
1594
|
this.ctx.transition("hand_idle");
|
|
1527
1595
|
}
|
|
1596
|
+
onExit() {
|
|
1597
|
+
this.panSession = null;
|
|
1598
|
+
}
|
|
1528
1599
|
onCancel() {
|
|
1529
1600
|
this.ctx.transition("hand_idle");
|
|
1530
1601
|
}
|
|
@@ -1752,8 +1823,7 @@ var Editor = class {
|
|
|
1752
1823
|
this.viewport = {
|
|
1753
1824
|
x: partial.x ?? this.viewport.x,
|
|
1754
1825
|
y: partial.y ?? this.viewport.y,
|
|
1755
|
-
zoom: Math.max(0.1, Math.min(4, rawZoom))
|
|
1756
|
-
rotation: partial.rotation ?? this.viewport.rotation
|
|
1826
|
+
zoom: Math.max(0.1, Math.min(4, rawZoom))
|
|
1757
1827
|
};
|
|
1758
1828
|
this.emitChange();
|
|
1759
1829
|
}
|
|
@@ -1767,10 +1837,6 @@ var Editor = class {
|
|
|
1767
1837
|
this.viewport = zoomViewport(this.viewport, factor, screenX, screenY);
|
|
1768
1838
|
this.emitChange();
|
|
1769
1839
|
}
|
|
1770
|
-
rotateAt(delta, screenX, screenY) {
|
|
1771
|
-
this.viewport = rotateViewport(this.viewport, delta, screenX, screenY);
|
|
1772
|
-
this.emitChange();
|
|
1773
|
-
}
|
|
1774
1840
|
deleteShapes(ids) {
|
|
1775
1841
|
if (ids.length === 0) return;
|
|
1776
1842
|
this.store.deleteShapes(ids);
|
|
@@ -1793,8 +1859,7 @@ var Editor = class {
|
|
|
1793
1859
|
viewport: {
|
|
1794
1860
|
x: this.viewport.x,
|
|
1795
1861
|
y: this.viewport.y,
|
|
1796
|
-
zoom: this.viewport.zoom
|
|
1797
|
-
rotation: this.viewport.rotation
|
|
1862
|
+
zoom: this.viewport.zoom
|
|
1798
1863
|
},
|
|
1799
1864
|
currentToolId: this.getCurrentToolId(),
|
|
1800
1865
|
drawStyle: this.getCurrentDrawStyle(),
|
|
@@ -1802,10 +1867,7 @@ var Editor = class {
|
|
|
1802
1867
|
};
|
|
1803
1868
|
}
|
|
1804
1869
|
loadSessionStateSnapshot(snapshot) {
|
|
1805
|
-
this.setViewport(
|
|
1806
|
-
...snapshot.viewport,
|
|
1807
|
-
rotation: snapshot.viewport.rotation ?? 0
|
|
1808
|
-
});
|
|
1870
|
+
this.setViewport(snapshot.viewport);
|
|
1809
1871
|
this.setCurrentDrawStyle({
|
|
1810
1872
|
color: snapshot.drawStyle.color,
|
|
1811
1873
|
dash: snapshot.drawStyle.dash,
|
|
@@ -2192,6 +2254,6 @@ function applyResize(editor, handle, startBounds, startShapes, pointer, lockAspe
|
|
|
2192
2254
|
}
|
|
2193
2255
|
}
|
|
2194
2256
|
|
|
2195
|
-
export { CanvasRenderer, CircleDrawingState, CircleIdleState, DEFAULT_COLORS, DRAG_DISTANCE_SQUARED, DocumentStore, ERASER_MARGIN, Editor, EraserErasingState, EraserIdleState, EraserPointingState, HandDraggingState, HandIdleState, InputManager, MAX_POINTS_PER_SHAPE, PenDrawingState, PenIdleState, STROKE_WIDTHS, SelectIdleState, SquareDrawingState, SquareIdleState, StateNode, ToolManager, applyMove, applyResize, applyRotation, boundsContainPoint, boundsIntersect, boundsOf, buildStartPositions, buildTransformSnapshots, closestOnSegment, createViewport, decodeFirstPoint, decodeLastPoint, decodePathToPoints, decodePoints, distance, documentSnapshotToRecords, encodePoints, getSelectionBoundsPage, getShapeBounds2 as getShapeBounds, getShapesInBounds, getTopShapeAtPoint, isSelectTool, minDistanceToPolyline, normalizeSelectionBounds, padBounds, pageToScreen, panViewport, pointHitsShape, recordsToDocumentSnapshot, resolveThemeColor, rotatePoint,
|
|
2257
|
+
export { CanvasRenderer, CircleDrawingState, CircleIdleState, DEFAULT_COLORS, DRAG_DISTANCE_SQUARED, DocumentStore, ERASER_MARGIN, Editor, EraserErasingState, EraserIdleState, EraserPointingState, HandDraggingState, HandIdleState, InputManager, MAX_POINTS_PER_SHAPE, PenDrawingState, PenIdleState, STROKE_WIDTHS, SelectIdleState, SquareDrawingState, SquareIdleState, StateNode, ToolManager, applyMove, applyResize, applyRotation, beginCameraPan, boundsContainPoint, boundsIntersect, boundsOf, buildStartPositions, buildTransformSnapshots, closestOnSegment, createViewport, decodeFirstPoint, decodeLastPoint, decodePathToPoints, decodePoints, distance, documentSnapshotToRecords, encodePoints, getSelectionBoundsPage, getShapeBounds2 as getShapeBounds, getShapesInBounds, getTopShapeAtPoint, isSelectTool, minDistanceToPolyline, moveCameraPan, normalizeSelectionBounds, padBounds, pageToScreen, panViewport, pointHitsShape, recordsToDocumentSnapshot, resolveThemeColor, rotatePoint, screenToPage, segmentHitsShape, segmentTouchesPolyline, setViewport, shapePagePoints, sqDistance, startCameraSlide, zoomViewport };
|
|
2196
2258
|
//# sourceMappingURL=index.js.map
|
|
2197
2259
|
//# sourceMappingURL=index.js.map
|