@fieldnotes/core 0.39.0 → 0.40.0
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 +165 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -3
- package/dist/index.d.ts +34 -3
- package/dist/index.js +164 -5
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -233,7 +233,7 @@ interface Tool {
|
|
|
233
233
|
setOptions?(options: object): void;
|
|
234
234
|
onOptionsChange?(listener: () => void): () => void;
|
|
235
235
|
}
|
|
236
|
-
type ToolName = 'hand' | 'select' | 'pencil' | 'eraser' | 'arrow' | 'note' | 'image' | 'text' | 'shape' | 'measure' | 'template';
|
|
236
|
+
type ToolName = 'hand' | 'select' | 'pencil' | 'eraser' | 'arrow' | 'note' | 'image' | 'text' | 'shape' | 'measure' | 'template' | 'laser';
|
|
237
237
|
|
|
238
238
|
declare function snapPoint(point: Point, gridSize: number): Point;
|
|
239
239
|
declare function snapToHexCenter(point: Point, cellSize: number, orientation: HexOrientation): Point;
|
|
@@ -1017,6 +1017,37 @@ declare class TemplateTool implements Tool {
|
|
|
1017
1017
|
private notifyOptionsChange;
|
|
1018
1018
|
}
|
|
1019
1019
|
|
|
1020
|
-
|
|
1020
|
+
interface LaserToolOptions {
|
|
1021
|
+
name?: string;
|
|
1022
|
+
color?: string;
|
|
1023
|
+
width?: number;
|
|
1024
|
+
fadeMs?: number;
|
|
1025
|
+
}
|
|
1026
|
+
declare class LaserTool implements Tool {
|
|
1027
|
+
readonly name: string;
|
|
1028
|
+
private color;
|
|
1029
|
+
private width;
|
|
1030
|
+
private fadeMs;
|
|
1031
|
+
private trail;
|
|
1032
|
+
private rafId;
|
|
1033
|
+
private drawing;
|
|
1034
|
+
private optionListeners;
|
|
1035
|
+
constructor(options?: LaserToolOptions);
|
|
1036
|
+
private now;
|
|
1037
|
+
onActivate(ctx: ToolContext): void;
|
|
1038
|
+
onDeactivate(ctx: ToolContext): void;
|
|
1039
|
+
getOptions(): LaserToolOptions;
|
|
1040
|
+
onOptionsChange(listener: () => void): () => void;
|
|
1041
|
+
setOptions(options: LaserToolOptions): void;
|
|
1042
|
+
onPointerDown(state: PointerState, ctx: ToolContext): void;
|
|
1043
|
+
onPointerMove(state: PointerState, ctx: ToolContext): void;
|
|
1044
|
+
onPointerUp(_state: PointerState, _ctx: ToolContext): void;
|
|
1045
|
+
renderOverlay(ctx: CanvasRenderingContext2D): void;
|
|
1046
|
+
private ensureAnimating;
|
|
1047
|
+
private tick;
|
|
1048
|
+
private notifyOptionsChange;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
declare const VERSION = "0.40.0";
|
|
1021
1052
|
|
|
1022
|
-
export { type ActiveFormats, type AlignEdge, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, type DistributeAxis, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportSvg, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
|
|
1053
|
+
export { type ActiveFormats, type AlignEdge, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, type DistributeAxis, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, LaserTool, type LaserToolOptions, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportSvg, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
|
package/dist/index.d.ts
CHANGED
|
@@ -233,7 +233,7 @@ interface Tool {
|
|
|
233
233
|
setOptions?(options: object): void;
|
|
234
234
|
onOptionsChange?(listener: () => void): () => void;
|
|
235
235
|
}
|
|
236
|
-
type ToolName = 'hand' | 'select' | 'pencil' | 'eraser' | 'arrow' | 'note' | 'image' | 'text' | 'shape' | 'measure' | 'template';
|
|
236
|
+
type ToolName = 'hand' | 'select' | 'pencil' | 'eraser' | 'arrow' | 'note' | 'image' | 'text' | 'shape' | 'measure' | 'template' | 'laser';
|
|
237
237
|
|
|
238
238
|
declare function snapPoint(point: Point, gridSize: number): Point;
|
|
239
239
|
declare function snapToHexCenter(point: Point, cellSize: number, orientation: HexOrientation): Point;
|
|
@@ -1017,6 +1017,37 @@ declare class TemplateTool implements Tool {
|
|
|
1017
1017
|
private notifyOptionsChange;
|
|
1018
1018
|
}
|
|
1019
1019
|
|
|
1020
|
-
|
|
1020
|
+
interface LaserToolOptions {
|
|
1021
|
+
name?: string;
|
|
1022
|
+
color?: string;
|
|
1023
|
+
width?: number;
|
|
1024
|
+
fadeMs?: number;
|
|
1025
|
+
}
|
|
1026
|
+
declare class LaserTool implements Tool {
|
|
1027
|
+
readonly name: string;
|
|
1028
|
+
private color;
|
|
1029
|
+
private width;
|
|
1030
|
+
private fadeMs;
|
|
1031
|
+
private trail;
|
|
1032
|
+
private rafId;
|
|
1033
|
+
private drawing;
|
|
1034
|
+
private optionListeners;
|
|
1035
|
+
constructor(options?: LaserToolOptions);
|
|
1036
|
+
private now;
|
|
1037
|
+
onActivate(ctx: ToolContext): void;
|
|
1038
|
+
onDeactivate(ctx: ToolContext): void;
|
|
1039
|
+
getOptions(): LaserToolOptions;
|
|
1040
|
+
onOptionsChange(listener: () => void): () => void;
|
|
1041
|
+
setOptions(options: LaserToolOptions): void;
|
|
1042
|
+
onPointerDown(state: PointerState, ctx: ToolContext): void;
|
|
1043
|
+
onPointerMove(state: PointerState, ctx: ToolContext): void;
|
|
1044
|
+
onPointerUp(_state: PointerState, _ctx: ToolContext): void;
|
|
1045
|
+
renderOverlay(ctx: CanvasRenderingContext2D): void;
|
|
1046
|
+
private ensureAnimating;
|
|
1047
|
+
private tick;
|
|
1048
|
+
private notifyOptionsChange;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
declare const VERSION = "0.40.0";
|
|
1021
1052
|
|
|
1022
|
-
export { type ActiveFormats, type AlignEdge, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, type DistributeAxis, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportSvg, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
|
|
1053
|
+
export { type ActiveFormats, type AlignEdge, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, type BackgroundOptions, type BackgroundPattern, type Binding, type Bounds, Camera, type CameraChangeInfo, type CameraOptions, type CanvasElement, type CanvasState, type Command, DEFAULT_NOTE_FONT_SIZE, type DistributeAxis, ElementStore, type ElementStyle, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, type ExportImageOptions, type ExportSvgOptions, type FontSizePreset, type GridElement, type GridInfo, HandTool, type HexOrientation, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, LaserTool, type LaserToolOptions, type Layer, LayerManager, MeasureTool, type MeasureToolOptions, type Measurement, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, type RenderStatsSnapshot, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type ShortcutBindings, type ShortcutOptions, type ShortcutsApi, type Size, type StrokeElement, type StrokePoint, type TemplateElement, type TemplateShape, TemplateTool, type TemplateToolOptions, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, VERSION, Viewport, type ViewportOptions, boundsIntersect, createArrow, createGrid, createHtmlElement, createImage, createNote, createShape, createStroke, createTemplate, createText, drawHexPath, exportImage, exportSvg, getActiveFormats, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getElementBounds, getElementStyle, getElementsBoundingBox, getHexCellsInCone, getHexCellsInLine, getHexCellsInRadius, getHexCellsInSquare, getHexDistance, isNearBezier, setFontSize, smartSnap, snapPoint, snapToHexCenter, styleToPatch, toggleBold, toggleItalic, toggleStrikethrough, toggleUnderline };
|
package/dist/index.js
CHANGED
|
@@ -831,6 +831,11 @@ var KeyboardActions = class {
|
|
|
831
831
|
if (tool?.name !== "select") return null;
|
|
832
832
|
return { tool, ctx };
|
|
833
833
|
}
|
|
834
|
+
selectableElements(ctx) {
|
|
835
|
+
return ctx.store.getAll().filter(
|
|
836
|
+
(el) => !el.locked && (ctx.isLayerVisible?.(el.layerId) ?? true) && !(ctx.isLayerLocked?.(el.layerId) ?? false)
|
|
837
|
+
);
|
|
838
|
+
}
|
|
834
839
|
nudge(dx, dy, byCell) {
|
|
835
840
|
if (this.deps.isToolActive()) return false;
|
|
836
841
|
const sel = this.selectTool();
|
|
@@ -973,12 +978,28 @@ var KeyboardActions = class {
|
|
|
973
978
|
}
|
|
974
979
|
const sel = this.selectTool();
|
|
975
980
|
if (!sel) return;
|
|
976
|
-
const ids = sel.ctx.
|
|
977
|
-
(el) => !el.locked && (sel.ctx.isLayerVisible?.(el.layerId) ?? true) && !(sel.ctx.isLayerLocked?.(el.layerId) ?? false)
|
|
978
|
-
).map((el) => el.id);
|
|
981
|
+
const ids = this.selectableElements(sel.ctx).map((el) => el.id);
|
|
979
982
|
sel.tool.setSelection(ids);
|
|
980
983
|
sel.ctx.requestRender();
|
|
981
984
|
}
|
|
985
|
+
cycleSelection(direction) {
|
|
986
|
+
if (this.deps.isToolActive()) return;
|
|
987
|
+
const tm = this.deps.getToolManager();
|
|
988
|
+
const ctx = this.deps.getToolContext();
|
|
989
|
+
if (!tm || !ctx) return;
|
|
990
|
+
if (tm.activeTool?.name !== "select") ctx.switchTool?.("select");
|
|
991
|
+
const sel = this.selectTool();
|
|
992
|
+
if (!sel) return;
|
|
993
|
+
const eligible = this.selectableElements(sel.ctx).filter((el) => el.type !== "grid");
|
|
994
|
+
if (eligible.length === 0) return;
|
|
995
|
+
const idxs = sel.tool.selectedIds.map((id) => eligible.findIndex((e) => e.id === id)).filter((i) => i >= 0);
|
|
996
|
+
const anchor = idxs.length === 0 ? direction > 0 ? -1 : 0 : direction > 0 ? Math.max(...idxs) : Math.min(...idxs);
|
|
997
|
+
const next = (anchor + direction + eligible.length) % eligible.length;
|
|
998
|
+
const target = eligible[next];
|
|
999
|
+
if (!target) return;
|
|
1000
|
+
sel.tool.setSelection([target.id]);
|
|
1001
|
+
sel.ctx.requestRender();
|
|
1002
|
+
}
|
|
982
1003
|
zoomToFit() {
|
|
983
1004
|
if (this.deps.isToolActive()) return;
|
|
984
1005
|
this.deps.fitToContent?.();
|
|
@@ -1083,6 +1104,8 @@ var DEFAULT_BINDINGS = [
|
|
|
1083
1104
|
["undo", ["mod+z"]],
|
|
1084
1105
|
["redo", ["mod+y", "mod+shift+z"]],
|
|
1085
1106
|
["select-all", ["mod+a"]],
|
|
1107
|
+
["cycle-selection", ["tab"]],
|
|
1108
|
+
["cycle-selection-reverse", ["shift+tab"]],
|
|
1086
1109
|
["copy", ["mod+c"]],
|
|
1087
1110
|
["duplicate", ["mod+d"]],
|
|
1088
1111
|
["z-forward", ["]"]],
|
|
@@ -1353,6 +1376,14 @@ var KeyboardHandler = class {
|
|
|
1353
1376
|
e?.preventDefault();
|
|
1354
1377
|
this.deps.actions.selectAll();
|
|
1355
1378
|
return;
|
|
1379
|
+
case "cycle-selection":
|
|
1380
|
+
e?.preventDefault();
|
|
1381
|
+
this.deps.actions.cycleSelection(1);
|
|
1382
|
+
return;
|
|
1383
|
+
case "cycle-selection-reverse":
|
|
1384
|
+
e?.preventDefault();
|
|
1385
|
+
this.deps.actions.cycleSelection(-1);
|
|
1386
|
+
return;
|
|
1356
1387
|
case "copy":
|
|
1357
1388
|
e?.preventDefault();
|
|
1358
1389
|
this.deps.actions.copy();
|
|
@@ -7691,6 +7722,17 @@ function renderArrowHandles(canvasCtx, arrow, zoom) {
|
|
|
7691
7722
|
canvasCtx.stroke();
|
|
7692
7723
|
}
|
|
7693
7724
|
}
|
|
7725
|
+
function renderArrowHoverHandle(canvasCtx, arrow, zoom) {
|
|
7726
|
+
const mid = getArrowMidpoint(arrow.from, arrow.to, arrow.bend);
|
|
7727
|
+
const radius = HANDLE_RADIUS / zoom;
|
|
7728
|
+
canvasCtx.fillStyle = "#2196F3";
|
|
7729
|
+
canvasCtx.strokeStyle = "#2196F3";
|
|
7730
|
+
canvasCtx.lineWidth = 1.5 / zoom;
|
|
7731
|
+
canvasCtx.beginPath();
|
|
7732
|
+
canvasCtx.arc(mid.x, mid.y, radius, 0, Math.PI * 2);
|
|
7733
|
+
canvasCtx.fill();
|
|
7734
|
+
canvasCtx.stroke();
|
|
7735
|
+
}
|
|
7694
7736
|
|
|
7695
7737
|
// src/elements/snap-guides.ts
|
|
7696
7738
|
function xAnchors(b) {
|
|
@@ -8539,7 +8581,13 @@ var SelectTool = class {
|
|
|
8539
8581
|
if (this.hoveredId && this.ctx && this.mode.type === "idle") {
|
|
8540
8582
|
if (!this._selectedIds.includes(this.hoveredId)) {
|
|
8541
8583
|
const el = this.ctx.store.getById(this.hoveredId);
|
|
8542
|
-
if (el) {
|
|
8584
|
+
if (el?.type === "arrow") {
|
|
8585
|
+
canvasCtx.save();
|
|
8586
|
+
canvasCtx.globalAlpha = 0.35;
|
|
8587
|
+
canvasCtx.setLineDash([]);
|
|
8588
|
+
renderArrowHoverHandle(canvasCtx, el, this.ctx.camera.zoom);
|
|
8589
|
+
canvasCtx.restore();
|
|
8590
|
+
} else if (el) {
|
|
8543
8591
|
const b = getElementBounds(el);
|
|
8544
8592
|
if (b) {
|
|
8545
8593
|
canvasCtx.save();
|
|
@@ -9510,8 +9558,118 @@ var TemplateTool = class {
|
|
|
9510
9558
|
}
|
|
9511
9559
|
};
|
|
9512
9560
|
|
|
9561
|
+
// src/tools/laser-tool.ts
|
|
9562
|
+
var DEFAULT_COLOR = "#ff3b30";
|
|
9563
|
+
var DEFAULT_WIDTH = 4;
|
|
9564
|
+
var DEFAULT_FADE_MS = 1200;
|
|
9565
|
+
var LaserTool = class {
|
|
9566
|
+
name;
|
|
9567
|
+
color;
|
|
9568
|
+
width;
|
|
9569
|
+
fadeMs;
|
|
9570
|
+
trail = [];
|
|
9571
|
+
rafId = null;
|
|
9572
|
+
drawing = false;
|
|
9573
|
+
optionListeners = /* @__PURE__ */ new Set();
|
|
9574
|
+
constructor(options = {}) {
|
|
9575
|
+
this.name = options.name ?? "laser";
|
|
9576
|
+
this.color = options.color ?? DEFAULT_COLOR;
|
|
9577
|
+
this.width = options.width ?? DEFAULT_WIDTH;
|
|
9578
|
+
this.fadeMs = options.fadeMs ?? DEFAULT_FADE_MS;
|
|
9579
|
+
}
|
|
9580
|
+
now() {
|
|
9581
|
+
return performance.now();
|
|
9582
|
+
}
|
|
9583
|
+
onActivate(ctx) {
|
|
9584
|
+
ctx.setCursor?.("crosshair");
|
|
9585
|
+
}
|
|
9586
|
+
onDeactivate(ctx) {
|
|
9587
|
+
if (this.rafId !== null) {
|
|
9588
|
+
cancelAnimationFrame(this.rafId);
|
|
9589
|
+
this.rafId = null;
|
|
9590
|
+
}
|
|
9591
|
+
this.trail = [];
|
|
9592
|
+
this.drawing = false;
|
|
9593
|
+
ctx.setCursor?.("default");
|
|
9594
|
+
ctx.requestRender();
|
|
9595
|
+
}
|
|
9596
|
+
getOptions() {
|
|
9597
|
+
return {
|
|
9598
|
+
name: this.name,
|
|
9599
|
+
color: this.color,
|
|
9600
|
+
width: this.width,
|
|
9601
|
+
fadeMs: this.fadeMs
|
|
9602
|
+
};
|
|
9603
|
+
}
|
|
9604
|
+
onOptionsChange(listener) {
|
|
9605
|
+
this.optionListeners.add(listener);
|
|
9606
|
+
return () => this.optionListeners.delete(listener);
|
|
9607
|
+
}
|
|
9608
|
+
setOptions(options) {
|
|
9609
|
+
if (options.color !== void 0) this.color = options.color;
|
|
9610
|
+
if (options.width !== void 0) this.width = options.width;
|
|
9611
|
+
if (options.fadeMs !== void 0) this.fadeMs = options.fadeMs;
|
|
9612
|
+
this.notifyOptionsChange();
|
|
9613
|
+
}
|
|
9614
|
+
onPointerDown(state, ctx) {
|
|
9615
|
+
this.drawing = true;
|
|
9616
|
+
const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });
|
|
9617
|
+
this.trail.push({ x: world.x, y: world.y, t: this.now() });
|
|
9618
|
+
this.ensureAnimating(ctx);
|
|
9619
|
+
}
|
|
9620
|
+
onPointerMove(state, ctx) {
|
|
9621
|
+
if (!this.drawing) return;
|
|
9622
|
+
const world = ctx.camera.screenToWorld({ x: state.x, y: state.y });
|
|
9623
|
+
this.trail.push({ x: world.x, y: world.y, t: this.now() });
|
|
9624
|
+
this.ensureAnimating(ctx);
|
|
9625
|
+
}
|
|
9626
|
+
onPointerUp(_state, _ctx) {
|
|
9627
|
+
this.drawing = false;
|
|
9628
|
+
}
|
|
9629
|
+
renderOverlay(ctx) {
|
|
9630
|
+
if (this.trail.length < 2) return;
|
|
9631
|
+
ctx.save();
|
|
9632
|
+
ctx.strokeStyle = this.color;
|
|
9633
|
+
ctx.lineWidth = this.width;
|
|
9634
|
+
ctx.lineCap = "round";
|
|
9635
|
+
ctx.lineJoin = "round";
|
|
9636
|
+
const now = this.now();
|
|
9637
|
+
for (let i = 0; i < this.trail.length - 1; i++) {
|
|
9638
|
+
const a = this.trail[i];
|
|
9639
|
+
const b = this.trail[i + 1];
|
|
9640
|
+
if (!a || !b) continue;
|
|
9641
|
+
const age = now - b.t;
|
|
9642
|
+
ctx.globalAlpha = Math.max(0, 1 - age / this.fadeMs);
|
|
9643
|
+
ctx.beginPath();
|
|
9644
|
+
ctx.moveTo(a.x, a.y);
|
|
9645
|
+
ctx.lineTo(b.x, b.y);
|
|
9646
|
+
ctx.stroke();
|
|
9647
|
+
}
|
|
9648
|
+
ctx.restore();
|
|
9649
|
+
}
|
|
9650
|
+
ensureAnimating(ctx) {
|
|
9651
|
+
if (this.rafId === null) {
|
|
9652
|
+
this.rafId = requestAnimationFrame(() => this.tick(ctx));
|
|
9653
|
+
}
|
|
9654
|
+
}
|
|
9655
|
+
tick(ctx) {
|
|
9656
|
+
const cutoff = this.now() - this.fadeMs;
|
|
9657
|
+
this.trail = this.trail.filter((p) => p.t >= cutoff);
|
|
9658
|
+
if (this.trail.length > 0) {
|
|
9659
|
+
ctx.requestRender();
|
|
9660
|
+
this.rafId = requestAnimationFrame(() => this.tick(ctx));
|
|
9661
|
+
} else {
|
|
9662
|
+
ctx.requestRender();
|
|
9663
|
+
this.rafId = null;
|
|
9664
|
+
}
|
|
9665
|
+
}
|
|
9666
|
+
notifyOptionsChange() {
|
|
9667
|
+
for (const listener of this.optionListeners) listener();
|
|
9668
|
+
}
|
|
9669
|
+
};
|
|
9670
|
+
|
|
9513
9671
|
// src/index.ts
|
|
9514
|
-
var VERSION = "0.
|
|
9672
|
+
var VERSION = "0.40.0";
|
|
9515
9673
|
export {
|
|
9516
9674
|
ArrowTool,
|
|
9517
9675
|
AutoSave,
|
|
@@ -9522,6 +9680,7 @@ export {
|
|
|
9522
9680
|
HandTool,
|
|
9523
9681
|
HistoryStack,
|
|
9524
9682
|
ImageTool,
|
|
9683
|
+
LaserTool,
|
|
9525
9684
|
LayerManager,
|
|
9526
9685
|
MeasureTool,
|
|
9527
9686
|
NoteTool,
|