@fieldnotes/core 0.6.1 → 0.7.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 +211 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +36 -2
- package/dist/index.d.ts +36 -2
- package/dist/index.js +210 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -85,7 +85,17 @@ interface ShapeElement extends BaseElement {
|
|
|
85
85
|
strokeWidth: number;
|
|
86
86
|
fillColor: string;
|
|
87
87
|
}
|
|
88
|
-
type
|
|
88
|
+
type HexOrientation = 'pointy' | 'flat';
|
|
89
|
+
interface GridElement extends BaseElement {
|
|
90
|
+
type: 'grid';
|
|
91
|
+
gridType: 'square' | 'hex';
|
|
92
|
+
hexOrientation: HexOrientation;
|
|
93
|
+
cellSize: number;
|
|
94
|
+
strokeColor: string;
|
|
95
|
+
strokeWidth: number;
|
|
96
|
+
opacity: number;
|
|
97
|
+
}
|
|
98
|
+
type CanvasElement = StrokeElement | NoteElement | ArrowElement | ImageElement | HtmlElement | TextElement | ShapeElement | GridElement;
|
|
89
99
|
type ElementType = CanvasElement['type'];
|
|
90
100
|
|
|
91
101
|
interface Layer {
|
|
@@ -437,6 +447,16 @@ declare class Viewport {
|
|
|
437
447
|
w: number;
|
|
438
448
|
h: number;
|
|
439
449
|
}): string;
|
|
450
|
+
addGrid(input: {
|
|
451
|
+
gridType?: 'square' | 'hex';
|
|
452
|
+
hexOrientation?: 'pointy' | 'flat';
|
|
453
|
+
cellSize?: number;
|
|
454
|
+
strokeColor?: string;
|
|
455
|
+
strokeWidth?: number;
|
|
456
|
+
opacity?: number;
|
|
457
|
+
}): string;
|
|
458
|
+
updateGrid(updates: Partial<Pick<GridElement, 'gridType' | 'hexOrientation' | 'cellSize' | 'strokeColor' | 'strokeWidth' | 'opacity'>>): void;
|
|
459
|
+
removeGrid(): void;
|
|
440
460
|
destroy(): void;
|
|
441
461
|
private startRenderLoop;
|
|
442
462
|
private render;
|
|
@@ -469,8 +489,12 @@ declare class ElementRenderer {
|
|
|
469
489
|
private store;
|
|
470
490
|
private imageCache;
|
|
471
491
|
private onImageLoad;
|
|
492
|
+
private camera;
|
|
493
|
+
private canvasSize;
|
|
472
494
|
setStore(store: ElementStore): void;
|
|
473
495
|
setOnImageLoad(callback: () => void): void;
|
|
496
|
+
setCamera(camera: Camera): void;
|
|
497
|
+
setCanvasSize(w: number, h: number): void;
|
|
474
498
|
isDomElement(element: CanvasElement): boolean;
|
|
475
499
|
renderCanvasElement(ctx: CanvasRenderingContext2D, element: CanvasElement): void;
|
|
476
500
|
private renderStroke;
|
|
@@ -480,6 +504,7 @@ declare class ElementRenderer {
|
|
|
480
504
|
private renderShape;
|
|
481
505
|
private fillShapePath;
|
|
482
506
|
private strokeShapePath;
|
|
507
|
+
private renderGrid;
|
|
483
508
|
private renderImage;
|
|
484
509
|
private getImage;
|
|
485
510
|
}
|
|
@@ -562,6 +587,15 @@ interface ShapeInput extends BaseDefaults {
|
|
|
562
587
|
fillColor?: string;
|
|
563
588
|
}
|
|
564
589
|
declare function createShape(input: ShapeInput): ShapeElement;
|
|
590
|
+
interface GridInput extends BaseDefaults {
|
|
591
|
+
gridType?: 'square' | 'hex';
|
|
592
|
+
hexOrientation?: HexOrientation;
|
|
593
|
+
cellSize?: number;
|
|
594
|
+
strokeColor?: string;
|
|
595
|
+
strokeWidth?: number;
|
|
596
|
+
opacity?: number;
|
|
597
|
+
}
|
|
598
|
+
declare function createGrid(input: GridInput): GridElement;
|
|
565
599
|
declare function createText(input: TextInput): TextElement;
|
|
566
600
|
|
|
567
601
|
interface Rect {
|
|
@@ -826,4 +860,4 @@ declare class UpdateLayerCommand implements Command {
|
|
|
826
860
|
|
|
827
861
|
declare const VERSION = "0.6.1";
|
|
828
862
|
|
|
829
|
-
export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, HandTool, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, type Layer, LayerManager, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, RemoveLayerCommand, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, clearStaleBindings, createArrow, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createText, exportState, findBindTarget, findBoundArrows, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, isBindable, isNearBezier, parseState, snapPoint, unbindArrow, updateBoundArrow };
|
|
863
|
+
export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type GridElement, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, type Layer, LayerManager, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, RemoveLayerCommand, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, clearStaleBindings, createArrow, createGrid, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createText, exportState, findBindTarget, findBoundArrows, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, isBindable, isNearBezier, parseState, snapPoint, unbindArrow, updateBoundArrow };
|
package/dist/index.d.ts
CHANGED
|
@@ -85,7 +85,17 @@ interface ShapeElement extends BaseElement {
|
|
|
85
85
|
strokeWidth: number;
|
|
86
86
|
fillColor: string;
|
|
87
87
|
}
|
|
88
|
-
type
|
|
88
|
+
type HexOrientation = 'pointy' | 'flat';
|
|
89
|
+
interface GridElement extends BaseElement {
|
|
90
|
+
type: 'grid';
|
|
91
|
+
gridType: 'square' | 'hex';
|
|
92
|
+
hexOrientation: HexOrientation;
|
|
93
|
+
cellSize: number;
|
|
94
|
+
strokeColor: string;
|
|
95
|
+
strokeWidth: number;
|
|
96
|
+
opacity: number;
|
|
97
|
+
}
|
|
98
|
+
type CanvasElement = StrokeElement | NoteElement | ArrowElement | ImageElement | HtmlElement | TextElement | ShapeElement | GridElement;
|
|
89
99
|
type ElementType = CanvasElement['type'];
|
|
90
100
|
|
|
91
101
|
interface Layer {
|
|
@@ -437,6 +447,16 @@ declare class Viewport {
|
|
|
437
447
|
w: number;
|
|
438
448
|
h: number;
|
|
439
449
|
}): string;
|
|
450
|
+
addGrid(input: {
|
|
451
|
+
gridType?: 'square' | 'hex';
|
|
452
|
+
hexOrientation?: 'pointy' | 'flat';
|
|
453
|
+
cellSize?: number;
|
|
454
|
+
strokeColor?: string;
|
|
455
|
+
strokeWidth?: number;
|
|
456
|
+
opacity?: number;
|
|
457
|
+
}): string;
|
|
458
|
+
updateGrid(updates: Partial<Pick<GridElement, 'gridType' | 'hexOrientation' | 'cellSize' | 'strokeColor' | 'strokeWidth' | 'opacity'>>): void;
|
|
459
|
+
removeGrid(): void;
|
|
440
460
|
destroy(): void;
|
|
441
461
|
private startRenderLoop;
|
|
442
462
|
private render;
|
|
@@ -469,8 +489,12 @@ declare class ElementRenderer {
|
|
|
469
489
|
private store;
|
|
470
490
|
private imageCache;
|
|
471
491
|
private onImageLoad;
|
|
492
|
+
private camera;
|
|
493
|
+
private canvasSize;
|
|
472
494
|
setStore(store: ElementStore): void;
|
|
473
495
|
setOnImageLoad(callback: () => void): void;
|
|
496
|
+
setCamera(camera: Camera): void;
|
|
497
|
+
setCanvasSize(w: number, h: number): void;
|
|
474
498
|
isDomElement(element: CanvasElement): boolean;
|
|
475
499
|
renderCanvasElement(ctx: CanvasRenderingContext2D, element: CanvasElement): void;
|
|
476
500
|
private renderStroke;
|
|
@@ -480,6 +504,7 @@ declare class ElementRenderer {
|
|
|
480
504
|
private renderShape;
|
|
481
505
|
private fillShapePath;
|
|
482
506
|
private strokeShapePath;
|
|
507
|
+
private renderGrid;
|
|
483
508
|
private renderImage;
|
|
484
509
|
private getImage;
|
|
485
510
|
}
|
|
@@ -562,6 +587,15 @@ interface ShapeInput extends BaseDefaults {
|
|
|
562
587
|
fillColor?: string;
|
|
563
588
|
}
|
|
564
589
|
declare function createShape(input: ShapeInput): ShapeElement;
|
|
590
|
+
interface GridInput extends BaseDefaults {
|
|
591
|
+
gridType?: 'square' | 'hex';
|
|
592
|
+
hexOrientation?: HexOrientation;
|
|
593
|
+
cellSize?: number;
|
|
594
|
+
strokeColor?: string;
|
|
595
|
+
strokeWidth?: number;
|
|
596
|
+
opacity?: number;
|
|
597
|
+
}
|
|
598
|
+
declare function createGrid(input: GridInput): GridElement;
|
|
565
599
|
declare function createText(input: TextInput): TextElement;
|
|
566
600
|
|
|
567
601
|
interface Rect {
|
|
@@ -826,4 +860,4 @@ declare class UpdateLayerCommand implements Command {
|
|
|
826
860
|
|
|
827
861
|
declare const VERSION = "0.6.1";
|
|
828
862
|
|
|
829
|
-
export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, HandTool, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, type Layer, LayerManager, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, RemoveLayerCommand, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, clearStaleBindings, createArrow, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createText, exportState, findBindTarget, findBoundArrows, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, isBindable, isNearBezier, parseState, snapPoint, unbindArrow, updateBoundArrow };
|
|
863
|
+
export { AddElementCommand, type ArrowElement, ArrowTool, type ArrowToolOptions, AutoSave, type AutoSaveOptions, Background, type BackgroundOptions, type BackgroundPattern, BatchCommand, type Binding, type Bounds, Camera, type CameraOptions, type CanvasElement, type CanvasState, type Command, CreateLayerCommand, ElementRenderer, ElementStore, type ElementType, type ElementUpdateEvent, EraserTool, type EraserToolOptions, EventBus, type GridElement, HandTool, type HexOrientation, HistoryRecorder, HistoryStack, type HistoryStackOptions, type HtmlElement, type ImageElement, ImageTool, type ImageToolOptions, InputHandler, type Layer, LayerManager, NoteEditor, type NoteElement, NoteTool, type NoteToolOptions, PencilTool, type PencilToolOptions, type Point, type PointerState, RemoveElementCommand, RemoveLayerCommand, SelectTool, type ShapeElement, type ShapeKind, ShapeTool, type ShapeToolOptions, type Size, type StrokeElement, type StrokePoint, type TextElement, TextTool, type TextToolOptions, type Tool, type ToolContext, ToolManager, type ToolName, UpdateElementCommand, UpdateLayerCommand, VERSION, Viewport, type ViewportOptions, clearStaleBindings, createArrow, createGrid, createHtmlElement, createId, createImage, createNote, createShape, createStroke, createText, exportState, findBindTarget, findBoundArrows, getArrowBounds, getArrowControlPoint, getArrowMidpoint, getArrowTangentAngle, getBendFromPoint, getEdgeIntersection, getElementBounds, getElementCenter, isBindable, isNearBezier, parseState, snapPoint, unbindArrow, updateBoundArrow };
|
package/dist/index.js
CHANGED
|
@@ -84,7 +84,7 @@ function validateState(data) {
|
|
|
84
84
|
];
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
|
-
var VALID_TYPES = /* @__PURE__ */ new Set(["stroke", "note", "arrow", "image", "html", "text", "shape"]);
|
|
87
|
+
var VALID_TYPES = /* @__PURE__ */ new Set(["stroke", "note", "arrow", "image", "html", "text", "shape", "grid"]);
|
|
88
88
|
function validateElement(el) {
|
|
89
89
|
if (!el || typeof el !== "object") {
|
|
90
90
|
throw new Error("Invalid element: expected an object");
|
|
@@ -945,6 +945,118 @@ function smoothToSegments(points) {
|
|
|
945
945
|
return segments;
|
|
946
946
|
}
|
|
947
947
|
|
|
948
|
+
// src/elements/grid-renderer.ts
|
|
949
|
+
function getSquareGridLines(bounds, cellSize) {
|
|
950
|
+
if (cellSize <= 0) return { verticals: [], horizontals: [] };
|
|
951
|
+
const verticals = [];
|
|
952
|
+
const startX = Math.floor(bounds.minX / cellSize) * cellSize;
|
|
953
|
+
const endX = Math.ceil(bounds.maxX / cellSize) * cellSize;
|
|
954
|
+
for (let x = startX; x <= endX; x += cellSize) {
|
|
955
|
+
verticals.push(x);
|
|
956
|
+
}
|
|
957
|
+
const horizontals = [];
|
|
958
|
+
const startY = Math.floor(bounds.minY / cellSize) * cellSize;
|
|
959
|
+
const endY = Math.ceil(bounds.maxY / cellSize) * cellSize;
|
|
960
|
+
for (let y = startY; y <= endY; y += cellSize) {
|
|
961
|
+
horizontals.push(y);
|
|
962
|
+
}
|
|
963
|
+
return { verticals, horizontals };
|
|
964
|
+
}
|
|
965
|
+
function getHexVertices(cx, cy, circumradius, orientation) {
|
|
966
|
+
const vertices = [];
|
|
967
|
+
const angleOffset = orientation === "pointy" ? -Math.PI / 2 : 0;
|
|
968
|
+
for (let i = 0; i < 6; i++) {
|
|
969
|
+
const angle = Math.PI / 3 * i + angleOffset;
|
|
970
|
+
vertices.push({
|
|
971
|
+
x: cx + circumradius * Math.cos(angle),
|
|
972
|
+
y: cy + circumradius * Math.sin(angle)
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
return vertices;
|
|
976
|
+
}
|
|
977
|
+
function getHexCenters(bounds, circumradius, orientation) {
|
|
978
|
+
if (circumradius <= 0) return [];
|
|
979
|
+
const centers = [];
|
|
980
|
+
if (orientation === "pointy") {
|
|
981
|
+
const hexW = Math.sqrt(3) * circumradius;
|
|
982
|
+
const hexH = 2 * circumradius;
|
|
983
|
+
const rowH = hexH * 0.75;
|
|
984
|
+
const startRow = Math.floor((bounds.minY - circumradius) / rowH);
|
|
985
|
+
const endRow = Math.ceil((bounds.maxY + circumradius) / rowH);
|
|
986
|
+
const startCol = Math.floor((bounds.minX - hexW) / hexW);
|
|
987
|
+
const endCol = Math.ceil((bounds.maxX + hexW) / hexW);
|
|
988
|
+
for (let row = startRow; row <= endRow; row++) {
|
|
989
|
+
const offsetX = row % 2 !== 0 ? hexW / 2 : 0;
|
|
990
|
+
for (let col = startCol; col <= endCol; col++) {
|
|
991
|
+
centers.push({
|
|
992
|
+
x: col * hexW + offsetX,
|
|
993
|
+
y: row * rowH
|
|
994
|
+
});
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
} else {
|
|
998
|
+
const hexW = 2 * circumradius;
|
|
999
|
+
const hexH = Math.sqrt(3) * circumradius;
|
|
1000
|
+
const colW = hexW * 0.75;
|
|
1001
|
+
const startCol = Math.floor((bounds.minX - circumradius) / colW);
|
|
1002
|
+
const endCol = Math.ceil((bounds.maxX + circumradius) / colW);
|
|
1003
|
+
const startRow = Math.floor((bounds.minY - hexH) / hexH);
|
|
1004
|
+
const endRow = Math.ceil((bounds.maxY + hexH) / hexH);
|
|
1005
|
+
for (let col = startCol; col <= endCol; col++) {
|
|
1006
|
+
const offsetY = col % 2 !== 0 ? hexH / 2 : 0;
|
|
1007
|
+
for (let row = startRow; row <= endRow; row++) {
|
|
1008
|
+
centers.push({
|
|
1009
|
+
x: col * colW,
|
|
1010
|
+
y: row * hexH + offsetY
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
}
|
|
1015
|
+
return centers;
|
|
1016
|
+
}
|
|
1017
|
+
function renderSquareGrid(ctx, bounds, cellSize, strokeColor, strokeWidth, opacity) {
|
|
1018
|
+
if (cellSize <= 0) return;
|
|
1019
|
+
const { verticals, horizontals } = getSquareGridLines(bounds, cellSize);
|
|
1020
|
+
ctx.save();
|
|
1021
|
+
ctx.strokeStyle = strokeColor;
|
|
1022
|
+
ctx.lineWidth = strokeWidth;
|
|
1023
|
+
ctx.globalAlpha = opacity;
|
|
1024
|
+
ctx.beginPath();
|
|
1025
|
+
for (const x of verticals) {
|
|
1026
|
+
ctx.moveTo(x, bounds.minY);
|
|
1027
|
+
ctx.lineTo(x, bounds.maxY);
|
|
1028
|
+
}
|
|
1029
|
+
for (const y of horizontals) {
|
|
1030
|
+
ctx.moveTo(bounds.minX, y);
|
|
1031
|
+
ctx.lineTo(bounds.maxX, y);
|
|
1032
|
+
}
|
|
1033
|
+
ctx.stroke();
|
|
1034
|
+
ctx.restore();
|
|
1035
|
+
}
|
|
1036
|
+
function renderHexGrid(ctx, bounds, cellSize, orientation, strokeColor, strokeWidth, opacity) {
|
|
1037
|
+
if (cellSize <= 0) return;
|
|
1038
|
+
const centers = getHexCenters(bounds, cellSize, orientation);
|
|
1039
|
+
ctx.save();
|
|
1040
|
+
ctx.strokeStyle = strokeColor;
|
|
1041
|
+
ctx.lineWidth = strokeWidth;
|
|
1042
|
+
ctx.globalAlpha = opacity;
|
|
1043
|
+
ctx.beginPath();
|
|
1044
|
+
for (const center of centers) {
|
|
1045
|
+
const verts = getHexVertices(center.x, center.y, cellSize, orientation);
|
|
1046
|
+
const first = verts[0];
|
|
1047
|
+
if (!first) continue;
|
|
1048
|
+
ctx.moveTo(first.x, first.y);
|
|
1049
|
+
for (let i = 1; i < verts.length; i++) {
|
|
1050
|
+
const v = verts[i];
|
|
1051
|
+
if (!v) continue;
|
|
1052
|
+
ctx.lineTo(v.x, v.y);
|
|
1053
|
+
}
|
|
1054
|
+
ctx.closePath();
|
|
1055
|
+
}
|
|
1056
|
+
ctx.stroke();
|
|
1057
|
+
ctx.restore();
|
|
1058
|
+
}
|
|
1059
|
+
|
|
948
1060
|
// src/elements/element-renderer.ts
|
|
949
1061
|
var DOM_ELEMENT_TYPES = /* @__PURE__ */ new Set(["note", "html", "text"]);
|
|
950
1062
|
var ARROWHEAD_LENGTH = 12;
|
|
@@ -953,12 +1065,20 @@ var ElementRenderer = class {
|
|
|
953
1065
|
store = null;
|
|
954
1066
|
imageCache = /* @__PURE__ */ new Map();
|
|
955
1067
|
onImageLoad = null;
|
|
1068
|
+
camera = null;
|
|
1069
|
+
canvasSize = null;
|
|
956
1070
|
setStore(store) {
|
|
957
1071
|
this.store = store;
|
|
958
1072
|
}
|
|
959
1073
|
setOnImageLoad(callback) {
|
|
960
1074
|
this.onImageLoad = callback;
|
|
961
1075
|
}
|
|
1076
|
+
setCamera(camera) {
|
|
1077
|
+
this.camera = camera;
|
|
1078
|
+
}
|
|
1079
|
+
setCanvasSize(w, h) {
|
|
1080
|
+
this.canvasSize = { w, h };
|
|
1081
|
+
}
|
|
962
1082
|
isDomElement(element) {
|
|
963
1083
|
return DOM_ELEMENT_TYPES.has(element.type);
|
|
964
1084
|
}
|
|
@@ -976,6 +1096,9 @@ var ElementRenderer = class {
|
|
|
976
1096
|
case "image":
|
|
977
1097
|
this.renderImage(ctx, element);
|
|
978
1098
|
break;
|
|
1099
|
+
case "grid":
|
|
1100
|
+
this.renderGrid(ctx, element);
|
|
1101
|
+
break;
|
|
979
1102
|
}
|
|
980
1103
|
}
|
|
981
1104
|
renderStroke(ctx, stroke) {
|
|
@@ -1111,6 +1234,42 @@ var ElementRenderer = class {
|
|
|
1111
1234
|
}
|
|
1112
1235
|
}
|
|
1113
1236
|
}
|
|
1237
|
+
renderGrid(ctx, grid) {
|
|
1238
|
+
if (!this.canvasSize) return;
|
|
1239
|
+
const cam = this.camera;
|
|
1240
|
+
if (!cam) return;
|
|
1241
|
+
const topLeft = cam.screenToWorld({ x: 0, y: 0 });
|
|
1242
|
+
const bottomRight = cam.screenToWorld({
|
|
1243
|
+
x: this.canvasSize.w,
|
|
1244
|
+
y: this.canvasSize.h
|
|
1245
|
+
});
|
|
1246
|
+
const bounds = {
|
|
1247
|
+
minX: topLeft.x,
|
|
1248
|
+
minY: topLeft.y,
|
|
1249
|
+
maxX: bottomRight.x,
|
|
1250
|
+
maxY: bottomRight.y
|
|
1251
|
+
};
|
|
1252
|
+
if (grid.gridType === "hex") {
|
|
1253
|
+
renderHexGrid(
|
|
1254
|
+
ctx,
|
|
1255
|
+
bounds,
|
|
1256
|
+
grid.cellSize,
|
|
1257
|
+
grid.hexOrientation,
|
|
1258
|
+
grid.strokeColor,
|
|
1259
|
+
grid.strokeWidth,
|
|
1260
|
+
grid.opacity
|
|
1261
|
+
);
|
|
1262
|
+
} else {
|
|
1263
|
+
renderSquareGrid(
|
|
1264
|
+
ctx,
|
|
1265
|
+
bounds,
|
|
1266
|
+
grid.cellSize,
|
|
1267
|
+
grid.strokeColor,
|
|
1268
|
+
grid.strokeWidth,
|
|
1269
|
+
grid.opacity
|
|
1270
|
+
);
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1114
1273
|
renderImage(ctx, image) {
|
|
1115
1274
|
const img = this.getImage(image.src);
|
|
1116
1275
|
if (!img) return;
|
|
@@ -1553,6 +1712,22 @@ function createShape(input) {
|
|
|
1553
1712
|
fillColor: input.fillColor ?? "none"
|
|
1554
1713
|
};
|
|
1555
1714
|
}
|
|
1715
|
+
function createGrid(input) {
|
|
1716
|
+
return {
|
|
1717
|
+
id: createId("grid"),
|
|
1718
|
+
type: "grid",
|
|
1719
|
+
position: input.position ?? { x: 0, y: 0 },
|
|
1720
|
+
zIndex: input.zIndex ?? 0,
|
|
1721
|
+
locked: input.locked ?? false,
|
|
1722
|
+
layerId: input.layerId ?? "",
|
|
1723
|
+
gridType: input.gridType ?? "square",
|
|
1724
|
+
hexOrientation: input.hexOrientation ?? "pointy",
|
|
1725
|
+
cellSize: input.cellSize ?? 40,
|
|
1726
|
+
strokeColor: input.strokeColor ?? "#000000",
|
|
1727
|
+
strokeWidth: input.strokeWidth ?? 1,
|
|
1728
|
+
opacity: input.opacity ?? 1
|
|
1729
|
+
};
|
|
1730
|
+
}
|
|
1556
1731
|
function createText(input) {
|
|
1557
1732
|
return {
|
|
1558
1733
|
id: createId("text"),
|
|
@@ -1730,6 +1905,7 @@ var Viewport = class {
|
|
|
1730
1905
|
this.toolManager = new ToolManager();
|
|
1731
1906
|
this.renderer = new ElementRenderer();
|
|
1732
1907
|
this.renderer.setStore(this.store);
|
|
1908
|
+
this.renderer.setCamera(this.camera);
|
|
1733
1909
|
this.renderer.setOnImageLoad(() => this.requestRender());
|
|
1734
1910
|
this.noteEditor = new NoteEditor();
|
|
1735
1911
|
this.noteEditor.setOnStop((id) => this.onTextEditStop(id));
|
|
@@ -1876,6 +2052,34 @@ var Viewport = class {
|
|
|
1876
2052
|
this.requestRender();
|
|
1877
2053
|
return el.id;
|
|
1878
2054
|
}
|
|
2055
|
+
addGrid(input) {
|
|
2056
|
+
const existing = this.store.getElementsByType("grid")[0];
|
|
2057
|
+
this.historyRecorder.begin();
|
|
2058
|
+
if (existing) {
|
|
2059
|
+
this.store.remove(existing.id);
|
|
2060
|
+
}
|
|
2061
|
+
const grid = createGrid({ ...input, layerId: this.layerManager.activeLayerId });
|
|
2062
|
+
this.store.add(grid);
|
|
2063
|
+
this.historyRecorder.commit();
|
|
2064
|
+
this.requestRender();
|
|
2065
|
+
return grid.id;
|
|
2066
|
+
}
|
|
2067
|
+
updateGrid(updates) {
|
|
2068
|
+
const grid = this.store.getElementsByType("grid")[0];
|
|
2069
|
+
if (!grid) return;
|
|
2070
|
+
this.historyRecorder.begin();
|
|
2071
|
+
this.store.update(grid.id, updates);
|
|
2072
|
+
this.historyRecorder.commit();
|
|
2073
|
+
this.requestRender();
|
|
2074
|
+
}
|
|
2075
|
+
removeGrid() {
|
|
2076
|
+
const grid = this.store.getElementsByType("grid")[0];
|
|
2077
|
+
if (!grid) return;
|
|
2078
|
+
this.historyRecorder.begin();
|
|
2079
|
+
this.store.remove(grid.id);
|
|
2080
|
+
this.historyRecorder.commit();
|
|
2081
|
+
this.requestRender();
|
|
2082
|
+
}
|
|
1879
2083
|
destroy() {
|
|
1880
2084
|
cancelAnimationFrame(this.animFrameId);
|
|
1881
2085
|
this.stopInteracting();
|
|
@@ -1907,6 +2111,7 @@ var Viewport = class {
|
|
|
1907
2111
|
const dpr = typeof devicePixelRatio !== "undefined" ? devicePixelRatio : 1;
|
|
1908
2112
|
ctx.save();
|
|
1909
2113
|
ctx.scale(dpr, dpr);
|
|
2114
|
+
this.renderer.setCanvasSize(this.canvasEl.clientWidth, this.canvasEl.clientHeight);
|
|
1910
2115
|
this.background.render(ctx, this.camera);
|
|
1911
2116
|
ctx.save();
|
|
1912
2117
|
ctx.translate(this.camera.position.x, this.camera.position.y);
|
|
@@ -2893,6 +3098,7 @@ var SelectTool = class {
|
|
|
2893
3098
|
for (const el of ctx.store.getAll()) {
|
|
2894
3099
|
if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) continue;
|
|
2895
3100
|
if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) continue;
|
|
3101
|
+
if (el.type === "grid") continue;
|
|
2896
3102
|
const bounds = this.getElementBounds(el);
|
|
2897
3103
|
if (bounds && this.rectsOverlap(marquee, bounds)) {
|
|
2898
3104
|
ids.push(el.id);
|
|
@@ -2929,11 +3135,13 @@ var SelectTool = class {
|
|
|
2929
3135
|
for (const el of elements) {
|
|
2930
3136
|
if (ctx.isLayerVisible && !ctx.isLayerVisible(el.layerId)) continue;
|
|
2931
3137
|
if (ctx.isLayerLocked && ctx.isLayerLocked(el.layerId)) continue;
|
|
3138
|
+
if (el.type === "grid") continue;
|
|
2932
3139
|
if (this.isInsideBounds(world, el)) return el;
|
|
2933
3140
|
}
|
|
2934
3141
|
return null;
|
|
2935
3142
|
}
|
|
2936
3143
|
isInsideBounds(point, el) {
|
|
3144
|
+
if (el.type === "grid") return false;
|
|
2937
3145
|
if ("size" in el) {
|
|
2938
3146
|
const s = el.size;
|
|
2939
3147
|
return point.x >= el.position.x && point.x <= el.position.x + s.w && point.y >= el.position.y && point.y <= el.position.y + s.h;
|
|
@@ -3393,6 +3601,7 @@ export {
|
|
|
3393
3601
|
Viewport,
|
|
3394
3602
|
clearStaleBindings,
|
|
3395
3603
|
createArrow,
|
|
3604
|
+
createGrid,
|
|
3396
3605
|
createHtmlElement,
|
|
3397
3606
|
createId,
|
|
3398
3607
|
createImage,
|