@markup-canvas/core 1.1.6 → 1.2.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.d.ts +1 -1
- package/dist/lib/MarkupCanvas.d.ts +10 -12
- package/dist/lib/actions/config/getConfig.d.ts +2 -0
- package/dist/lib/actions/index.d.ts +3 -0
- package/dist/lib/actions/pan/centerContent.d.ts +2 -0
- package/dist/lib/actions/pan/index.d.ts +6 -0
- package/dist/lib/actions/pan/panDown.d.ts +2 -0
- package/dist/lib/actions/pan/panLeft.d.ts +2 -0
- package/dist/lib/actions/pan/panRight.d.ts +2 -0
- package/dist/lib/actions/pan/panUp.d.ts +2 -0
- package/dist/lib/actions/pan/scrollToPoint.d.ts +2 -0
- package/dist/lib/actions/transform/index.d.ts +2 -0
- package/dist/lib/actions/transform/resetTransform.d.ts +2 -0
- package/dist/lib/actions/transform/updateTransform.d.ts +2 -0
- package/dist/lib/actions/ui/grid/hideGrid.d.ts +2 -0
- package/dist/lib/actions/ui/grid/index.d.ts +4 -0
- package/dist/lib/actions/ui/grid/isGridVisible.d.ts +2 -0
- package/dist/lib/actions/ui/grid/showGrid.d.ts +2 -0
- package/dist/lib/actions/ui/grid/toggleGrid.d.ts +2 -0
- package/dist/lib/actions/ui/index.d.ts +4 -0
- package/dist/lib/actions/ui/rulers/areRulersVisible.d.ts +2 -0
- package/dist/lib/actions/ui/rulers/hideRulers.d.ts +2 -0
- package/dist/lib/actions/ui/rulers/index.d.ts +4 -0
- package/dist/lib/actions/ui/rulers/showRulers.d.ts +2 -0
- package/dist/lib/actions/ui/rulers/toggleRulers.d.ts +2 -0
- package/dist/lib/actions/ui/toggleTransition.d.ts +1 -0
- package/dist/lib/actions/ui/updateThemeMode.d.ts +2 -0
- package/dist/lib/actions/zoom/index.d.ts +6 -0
- package/dist/lib/actions/zoom/resetView.d.ts +2 -0
- package/dist/lib/actions/zoom/resetViewToCenter.d.ts +3 -0
- package/dist/lib/actions/zoom/setZoom.d.ts +3 -0
- package/dist/lib/actions/zoom/zoomIn.d.ts +3 -0
- package/dist/lib/actions/zoom/zoomOut.d.ts +3 -0
- package/dist/lib/actions/zoom/zoomToPoint.d.ts +2 -0
- package/dist/lib/canvas/createCanvas.d.ts +2 -2
- package/dist/lib/canvas/fitToScreen.d.ts +2 -0
- package/dist/lib/canvas/getCanvasBounds.d.ts +2 -2
- package/dist/lib/canvas/index.d.ts +1 -1
- package/dist/lib/events/emitTransformEvents.d.ts +3 -0
- package/dist/lib/events/keyboard/handleKeyDown.d.ts +3 -2
- package/dist/lib/events/keyboard/handleKeyUp.d.ts +3 -2
- package/dist/lib/events/keyboard/setupKeyboardEvents.d.ts +3 -2
- package/dist/lib/events/mouse/createMouseDragControls.d.ts +7 -0
- package/dist/lib/events/mouse/handleClickToZoom.d.ts +3 -2
- package/dist/lib/events/mouse/handleMouseDown.d.ts +3 -2
- package/dist/lib/events/mouse/handleMouseLeave.d.ts +3 -2
- package/dist/lib/events/mouse/handleMouseMove.d.ts +3 -2
- package/dist/lib/events/mouse/handleMouseUp.d.ts +3 -2
- package/dist/lib/events/mouse/setupMouseDrag.d.ts +4 -3
- package/dist/lib/events/mouse/setupMouseEvents.d.ts +4 -3
- package/dist/lib/events/touch/handleTouchMove.d.ts +3 -2
- package/dist/lib/events/touch/setupTouchEvents.d.ts +2 -2
- package/dist/lib/events/trackpad/createTrackpadPanHandler.d.ts +2 -2
- package/dist/lib/events/utils/getAdaptiveZoomSpeed.d.ts +2 -2
- package/dist/lib/events/utils/getViewportCenter.d.ts +5 -0
- package/dist/lib/events/utils/resetDragState.d.ts +3 -2
- package/dist/lib/events/utils/updateCursor.d.ts +3 -2
- package/dist/lib/events/wheel/handleWheel.d.ts +3 -2
- package/dist/lib/events/wheel/setupWheelEvents.d.ts +3 -2
- package/dist/lib/events/wheel/setupWheelHandler.d.ts +3 -2
- package/dist/lib/helpers/getVisibleArea.d.ts +7 -0
- package/dist/lib/helpers/index.d.ts +2 -0
- package/dist/lib/helpers/isPointVisible.d.ts +2 -0
- package/dist/lib/transform/applyZoomToCanvas.d.ts +2 -2
- package/dist/lib/window/bindCanvasToWindow.d.ts +3 -0
- package/dist/lib/window/broadcastEvent.d.ts +2 -0
- package/dist/lib/window/cleanupWindowBinding.d.ts +2 -0
- package/dist/lib/window/index.d.ts +3 -0
- package/dist/markup-canvas.cjs.js +715 -554
- package/dist/markup-canvas.esm.js +715 -554
- package/dist/markup-canvas.umd.js +711 -547
- package/dist/markup-canvas.umd.min.js +1 -1
- package/dist/types/canvas.d.ts +1 -47
- package/dist/types/config.d.ts +0 -3
- package/dist/types/events.d.ts +4 -1
- package/dist/types/index.d.ts +3 -2
- package/dist/types/window.d.ts +84 -0
- package/package.json +1 -1
- package/src/index.ts +1 -1
- package/src/lib/MarkupCanvas.ts +142 -308
- package/src/lib/actions/config/getConfig.ts +5 -0
- package/src/lib/actions/index.ts +6 -0
- package/src/lib/actions/pan/centerContent.ts +21 -0
- package/src/lib/actions/pan/index.ts +6 -0
- package/src/lib/actions/pan/panDown.ts +13 -0
- package/src/lib/actions/pan/panLeft.ts +13 -0
- package/src/lib/actions/pan/panRight.ts +13 -0
- package/src/lib/actions/pan/panUp.ts +13 -0
- package/src/lib/actions/pan/scrollToPoint.ts +27 -0
- package/src/lib/actions/transform/index.ts +2 -0
- package/src/lib/actions/transform/resetTransform.ts +11 -0
- package/src/lib/actions/transform/updateTransform.ts +9 -0
- package/src/lib/actions/ui/grid/hideGrid.ts +9 -0
- package/src/lib/actions/ui/grid/index.ts +4 -0
- package/src/lib/actions/ui/grid/isGridVisible.ts +8 -0
- package/src/lib/actions/ui/grid/showGrid.ts +9 -0
- package/src/lib/actions/ui/grid/toggleGrid.ts +9 -0
- package/src/lib/actions/ui/index.ts +4 -0
- package/src/lib/actions/ui/rulers/areRulersVisible.ts +8 -0
- package/src/lib/actions/ui/rulers/hideRulers.ts +9 -0
- package/src/lib/actions/ui/rulers/index.ts +4 -0
- package/src/lib/actions/ui/rulers/showRulers.ts +9 -0
- package/src/lib/actions/ui/rulers/toggleRulers.ts +14 -0
- package/src/lib/actions/ui/toggleTransition.ts +3 -0
- package/src/lib/actions/ui/updateThemeMode.ts +25 -0
- package/src/lib/actions/zoom/index.ts +6 -0
- package/src/lib/actions/zoom/resetView.ts +17 -0
- package/src/lib/actions/zoom/resetViewToCenter.ts +21 -0
- package/src/lib/actions/zoom/setZoom.ts +22 -0
- package/src/lib/actions/zoom/zoomIn.ts +21 -0
- package/src/lib/actions/zoom/zoomOut.ts +21 -0
- package/src/lib/actions/zoom/zoomToPoint.ts +18 -0
- package/src/lib/canvas/createCanvas.ts +6 -14
- package/src/lib/canvas/fitToScreen.ts +27 -0
- package/src/lib/canvas/getCanvasBounds.ts +3 -4
- package/src/lib/canvas/index.ts +1 -1
- package/src/lib/config/constants.ts +2 -6
- package/src/lib/config/presets/editor-preset.ts +4 -8
- package/src/lib/events/emitTransformEvents.ts +9 -0
- package/src/lib/events/keyboard/handleKeyDown.ts +3 -2
- package/src/lib/events/keyboard/handleKeyUp.ts +3 -2
- package/src/lib/events/keyboard/setupKeyboardEvents.ts +18 -38
- package/src/lib/events/mouse/createMouseDragControls.ts +21 -0
- package/src/lib/events/mouse/handleClickToZoom.ts +3 -2
- package/src/lib/events/mouse/handleMouseDown.ts +3 -2
- package/src/lib/events/mouse/handleMouseLeave.ts +3 -2
- package/src/lib/events/mouse/handleMouseMove.ts +3 -2
- package/src/lib/events/mouse/handleMouseUp.ts +3 -2
- package/src/lib/events/mouse/setupMouseDrag.ts +5 -4
- package/src/lib/events/mouse/setupMouseEvents.ts +5 -4
- package/src/lib/events/postMessage/setupPostMessageEvents.ts +10 -0
- package/src/lib/events/touch/handleTouchMove.ts +3 -2
- package/src/lib/events/touch/setupTouchEvents.ts +3 -2
- package/src/lib/events/trackpad/createTrackpadPanHandler.ts +3 -2
- package/src/lib/events/utils/getAdaptiveZoomSpeed.ts +2 -2
- package/src/lib/events/utils/getViewportCenter.ts +14 -0
- package/src/lib/events/utils/resetDragState.ts +3 -2
- package/src/lib/events/utils/updateCursor.ts +3 -2
- package/src/lib/events/wheel/handleWheel.ts +3 -2
- package/src/lib/events/wheel/setupWheelEvents.ts +3 -2
- package/src/lib/events/wheel/setupWheelHandler.ts +3 -2
- package/src/lib/helpers/getVisibleArea.ts +6 -0
- package/src/lib/helpers/index.ts +2 -0
- package/src/lib/helpers/isPointVisible.ts +7 -0
- package/src/lib/rulers/createRulers.ts +0 -1
- package/src/lib/transform/applyZoomToCanvas.ts +2 -2
- package/src/lib/window/bindCanvasToWindow.ts +128 -0
- package/src/lib/window/broadcastEvent.ts +38 -0
- package/src/lib/window/cleanupWindowBinding.ts +15 -0
- package/src/lib/window/index.ts +3 -0
- package/src/types/canvas.ts +1 -47
- package/src/types/config.ts +1 -7
- package/src/types/events.ts +7 -1
- package/src/types/index.ts +4 -2
- package/src/types/window.ts +77 -0
- package/dist/lib/canvas/config.d.ts +0 -2
- package/dist/lib/canvas/getCanvasMethods.d.ts +0 -12
- package/dist/lib/events/keyboard/setupKeyboardNavigation.d.ts +0 -2
- package/src/lib/canvas/config.ts +0 -29
- package/src/lib/canvas/getCanvasMethods.ts +0 -102
- package/src/lib/events/keyboard/setupKeyboardNavigation.ts +0 -115
- /package/dist/lib/canvas/{calcVisibleArea.d.ts → calculateVisibleArea.d.ts} +0 -0
- /package/src/lib/canvas/{calcVisibleArea.ts → calculateVisibleArea.ts} +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Markup Canvas
|
|
3
3
|
* High-performance markup canvas with zoom and pan capabilities
|
|
4
|
-
* @version 1.
|
|
4
|
+
* @version 1.2.0
|
|
5
5
|
*/
|
|
6
6
|
'use strict';
|
|
7
7
|
|
|
@@ -12,16 +12,15 @@ const EDITOR_PRESET = {
|
|
|
12
12
|
width: 4000,
|
|
13
13
|
height: 4000,
|
|
14
14
|
enableAcceleration: true,
|
|
15
|
-
// Global
|
|
16
|
-
bindToWindow: true,
|
|
15
|
+
// Global Instance Access
|
|
17
16
|
name: "canvas",
|
|
18
17
|
enablePostMessageAPI: true,
|
|
19
18
|
// Interaction controls
|
|
20
19
|
enableZoom: true,
|
|
21
20
|
enablePan: true,
|
|
22
21
|
enableTouch: true,
|
|
23
|
-
enableKeyboard:
|
|
24
|
-
bindKeyboardEventsTo: "
|
|
22
|
+
enableKeyboard: true,
|
|
23
|
+
bindKeyboardEventsTo: "document",
|
|
25
24
|
// Zoom behavior
|
|
26
25
|
zoomSpeed: 1.5,
|
|
27
26
|
minZoom: 0.05,
|
|
@@ -43,7 +42,7 @@ const EDITOR_PRESET = {
|
|
|
43
42
|
requireOptionForClickZoom: true,
|
|
44
43
|
// Visual elements
|
|
45
44
|
enableRulers: true,
|
|
46
|
-
enableGrid:
|
|
45
|
+
enableGrid: true,
|
|
47
46
|
showRulers: true,
|
|
48
47
|
showGrid: false,
|
|
49
48
|
rulerFontSize: 9,
|
|
@@ -67,72 +66,8 @@ const EDITOR_PRESET = {
|
|
|
67
66
|
gridColorDark: "rgba(232, 86, 193, 0.5)",
|
|
68
67
|
// Theme
|
|
69
68
|
themeMode: "light",
|
|
70
|
-
// Callbacks
|
|
71
|
-
onTransformUpdate: () => { },
|
|
72
69
|
};
|
|
73
70
|
|
|
74
|
-
// Default transform values
|
|
75
|
-
const DEFAULT_ZOOM = 1.0;
|
|
76
|
-
// Validation thresholds
|
|
77
|
-
const ZOOM_CHANGE_THRESHOLD = 0.001;
|
|
78
|
-
// CSS transition values
|
|
79
|
-
const FALLBACK_TRANSITION_DURATION = 0.2;
|
|
80
|
-
// Zoom to fit padding factor
|
|
81
|
-
const ZOOM_FIT_PADDING = 0.9;
|
|
82
|
-
// CSS class names
|
|
83
|
-
const CANVAS_CONTAINER_CLASS = "canvas-container";
|
|
84
|
-
const TRANSFORM_LAYER_CLASS = "transform-layer";
|
|
85
|
-
const CONTENT_LAYER_CLASS = "content-layer";
|
|
86
|
-
|
|
87
|
-
function moveExistingContent(existingContent, contentLayer, transformLayer) {
|
|
88
|
-
existingContent.forEach((child) => {
|
|
89
|
-
if (child !== transformLayer && !child.classList.contains(TRANSFORM_LAYER_CLASS)) {
|
|
90
|
-
contentLayer.appendChild(child);
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function setupContentLayer(contentLayer) {
|
|
96
|
-
contentLayer.style.position = "relative";
|
|
97
|
-
contentLayer.style.width = "100%";
|
|
98
|
-
contentLayer.style.height = "100%";
|
|
99
|
-
contentLayer.style.pointerEvents = "auto";
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Sets up the transform layer with proper styles and dimensions
|
|
103
|
-
function setupTransformLayer(transformLayer, config) {
|
|
104
|
-
transformLayer.style.position = "absolute";
|
|
105
|
-
const rulerOffset = config.rulerSize;
|
|
106
|
-
transformLayer.style.top = `${rulerOffset}px`;
|
|
107
|
-
transformLayer.style.left = `${rulerOffset}px`;
|
|
108
|
-
transformLayer.style.width = `${config.width}px`;
|
|
109
|
-
transformLayer.style.height = `${config.height}px`;
|
|
110
|
-
transformLayer.style.transformOrigin = "0 0";
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function createCanvasLayers(container, config) {
|
|
114
|
-
const existingContent = Array.from(container.children);
|
|
115
|
-
// Create or find transform layer
|
|
116
|
-
let transformLayer = container.querySelector(`.${TRANSFORM_LAYER_CLASS}`);
|
|
117
|
-
if (!transformLayer) {
|
|
118
|
-
transformLayer = document.createElement("div");
|
|
119
|
-
transformLayer.className = TRANSFORM_LAYER_CLASS;
|
|
120
|
-
container.appendChild(transformLayer);
|
|
121
|
-
}
|
|
122
|
-
setupTransformLayer(transformLayer, config);
|
|
123
|
-
// Create or find content layer
|
|
124
|
-
let contentLayer = transformLayer.querySelector(`.${CONTENT_LAYER_CLASS}`);
|
|
125
|
-
if (!contentLayer) {
|
|
126
|
-
contentLayer = document.createElement("div");
|
|
127
|
-
contentLayer.className = CONTENT_LAYER_CLASS;
|
|
128
|
-
transformLayer.appendChild(contentLayer);
|
|
129
|
-
moveExistingContent(existingContent, contentLayer, transformLayer);
|
|
130
|
-
}
|
|
131
|
-
// Set content layer properties
|
|
132
|
-
setupContentLayer(contentLayer);
|
|
133
|
-
return { transformLayer, contentLayer };
|
|
134
|
-
}
|
|
135
|
-
|
|
136
71
|
function canvasToContent(canvasX, canvasY, matrix) {
|
|
137
72
|
if (!matrix?.inverse) {
|
|
138
73
|
return { x: canvasX, y: canvasY };
|
|
@@ -160,6 +95,19 @@ function createMatrix(scale, translateX, translateY) {
|
|
|
160
95
|
return new DOMMatrix([scale, 0, 0, scale, translateX, translateY]);
|
|
161
96
|
}
|
|
162
97
|
|
|
98
|
+
// Default transform values
|
|
99
|
+
const DEFAULT_ZOOM = 1.0;
|
|
100
|
+
// Validation thresholds
|
|
101
|
+
const ZOOM_CHANGE_THRESHOLD = 0.001;
|
|
102
|
+
// CSS transition values
|
|
103
|
+
const FALLBACK_TRANSITION_DURATION = 0.2;
|
|
104
|
+
// Zoom to fit padding factor
|
|
105
|
+
const ZOOM_FIT_PADDING = 0.9;
|
|
106
|
+
// CSS class names
|
|
107
|
+
const CANVAS_CONTAINER_CLASS = "canvas-container";
|
|
108
|
+
const TRANSFORM_LAYER_CLASS = "transform-layer";
|
|
109
|
+
const CONTENT_LAYER_CLASS = "content-layer";
|
|
110
|
+
|
|
163
111
|
function getZoomToMouseTransform(mouseX, mouseY, currentTransform, zoomFactor, config) {
|
|
164
112
|
const rulerOffset = config.enableRulers ? -config.rulerSize : 0;
|
|
165
113
|
const transform = currentTransform || {
|
|
@@ -221,6 +169,16 @@ function getEmptyBounds() {
|
|
|
221
169
|
};
|
|
222
170
|
}
|
|
223
171
|
|
|
172
|
+
function getVisibleArea(canvas) {
|
|
173
|
+
const bounds = canvas.getBounds();
|
|
174
|
+
return bounds.visibleArea;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function isPointVisible(canvas, x, y) {
|
|
178
|
+
const visibleArea = getVisibleArea(canvas);
|
|
179
|
+
return x >= visibleArea.x && x <= visibleArea.x + visibleArea.width && y >= visibleArea.y && y <= visibleArea.y + visibleArea.height;
|
|
180
|
+
}
|
|
181
|
+
|
|
224
182
|
function withClampedZoom(config, operation) {
|
|
225
183
|
const clampFunction = (scale) => clampZoom(scale, config);
|
|
226
184
|
return operation(clampFunction);
|
|
@@ -276,13 +234,6 @@ function withRulerSize(canvas, rulerSize, operation) {
|
|
|
276
234
|
const finalRulerSize = hasRulers ? rulerSize : 0;
|
|
277
235
|
return operation(finalRulerSize);
|
|
278
236
|
}
|
|
279
|
-
function withRulerOffsets(canvas, rulerSize, x, y, operation) {
|
|
280
|
-
return withRulerSize(canvas, rulerSize, (rulerSize) => {
|
|
281
|
-
const adjustedX = x - rulerSize;
|
|
282
|
-
const adjustedY = y - rulerSize;
|
|
283
|
-
return operation(adjustedX, adjustedY);
|
|
284
|
-
});
|
|
285
|
-
}
|
|
286
237
|
function withRulerOffsetObject(canvas, rulerSize, coords, operation) {
|
|
287
238
|
return withRulerSize(canvas, rulerSize, (rulerSize) => {
|
|
288
239
|
const adjusted = {
|
|
@@ -314,8 +265,7 @@ const DEFAULT_CONFIG = {
|
|
|
314
265
|
width: 8000,
|
|
315
266
|
height: 8000,
|
|
316
267
|
enableAcceleration: true,
|
|
317
|
-
// Global
|
|
318
|
-
bindToWindow: false,
|
|
268
|
+
// Global Instance Access
|
|
319
269
|
name: "markupCanvas",
|
|
320
270
|
enablePostMessageAPI: false,
|
|
321
271
|
// Interaction controls
|
|
@@ -323,7 +273,7 @@ const DEFAULT_CONFIG = {
|
|
|
323
273
|
enablePan: true,
|
|
324
274
|
enableTouch: true,
|
|
325
275
|
enableKeyboard: true,
|
|
326
|
-
bindKeyboardEventsTo: "
|
|
276
|
+
bindKeyboardEventsTo: "document",
|
|
327
277
|
// Zoom behavior
|
|
328
278
|
zoomSpeed: 1.5,
|
|
329
279
|
minZoom: 0.05,
|
|
@@ -369,14 +319,11 @@ const DEFAULT_CONFIG = {
|
|
|
369
319
|
gridColorDark: "rgba(232, 86, 193, 0.5)",
|
|
370
320
|
// Theme
|
|
371
321
|
themeMode: "light",
|
|
372
|
-
// Callbacks
|
|
373
|
-
onTransformUpdate: () => { },
|
|
374
322
|
};
|
|
375
323
|
|
|
376
|
-
function getCanvasBounds(canvas) {
|
|
324
|
+
function getCanvasBounds(canvas, config) {
|
|
377
325
|
try {
|
|
378
326
|
const container = canvas.container;
|
|
379
|
-
const config = canvas.config;
|
|
380
327
|
const transform = canvas.transform || {
|
|
381
328
|
scale: 1.0,
|
|
382
329
|
translateX: 0,
|
|
@@ -426,6 +373,116 @@ function getCanvasBounds(canvas) {
|
|
|
426
373
|
}
|
|
427
374
|
}
|
|
428
375
|
|
|
376
|
+
function disableTransition(element, config) {
|
|
377
|
+
try {
|
|
378
|
+
if (config.enableTransition) {
|
|
379
|
+
if (window.__markupCanvasTransitionTimeout) {
|
|
380
|
+
clearTimeout(window.__markupCanvasTransitionTimeout);
|
|
381
|
+
window.__markupCanvasTransitionTimeout = undefined;
|
|
382
|
+
}
|
|
383
|
+
const delay = (config.transitionDuration ?? FALLBACK_TRANSITION_DURATION) * 1000;
|
|
384
|
+
withDebounce("disableTransition", delay, () => {
|
|
385
|
+
element.style.transition = "none";
|
|
386
|
+
window.__markupCanvasTransitionTimeout = undefined;
|
|
387
|
+
});
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
return false;
|
|
391
|
+
}
|
|
392
|
+
catch (error) {
|
|
393
|
+
console.error("Failed to disable transitions:", error);
|
|
394
|
+
return true;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
function enableTransition(element, config) {
|
|
399
|
+
try {
|
|
400
|
+
if (config.enableTransition) {
|
|
401
|
+
if (window.__markupCanvasTransitionTimeout) {
|
|
402
|
+
clearTimeout(window.__markupCanvasTransitionTimeout);
|
|
403
|
+
window.__markupCanvasTransitionTimeout = undefined;
|
|
404
|
+
}
|
|
405
|
+
element.style.transition = `transform ${config.transitionDuration}s linear`;
|
|
406
|
+
return true;
|
|
407
|
+
}
|
|
408
|
+
return false;
|
|
409
|
+
}
|
|
410
|
+
catch (error) {
|
|
411
|
+
console.error("Failed to enable transitions:", error);
|
|
412
|
+
return false;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
function withTransition(element, config, operation) {
|
|
417
|
+
enableTransition(element, config);
|
|
418
|
+
try {
|
|
419
|
+
const result = operation();
|
|
420
|
+
return result;
|
|
421
|
+
}
|
|
422
|
+
finally {
|
|
423
|
+
disableTransition(element, config);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function centerContent(canvas, config, updateTransformFn, transformLayer) {
|
|
428
|
+
return withTransition(transformLayer, config, () => {
|
|
429
|
+
const bounds = getCanvasBounds(canvas, config);
|
|
430
|
+
const centerX = (bounds.width - bounds.contentWidth * canvas.transform.scale) / 2;
|
|
431
|
+
const centerY = (bounds.height - bounds.contentHeight * canvas.transform.scale) / 2;
|
|
432
|
+
return updateTransformFn({
|
|
433
|
+
translateX: centerX,
|
|
434
|
+
translateY: centerY,
|
|
435
|
+
});
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function panDown(canvas, config, updateTransform) {
|
|
440
|
+
const panDistance = config.keyboardPanStep;
|
|
441
|
+
const newTransform = {
|
|
442
|
+
translateY: canvas.transform.translateY - panDistance,
|
|
443
|
+
};
|
|
444
|
+
return updateTransform(newTransform);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function panLeft(canvas, config, updateTransform) {
|
|
448
|
+
const panDistance = config.keyboardPanStep;
|
|
449
|
+
const newTransform = {
|
|
450
|
+
translateX: canvas.transform.translateX + panDistance,
|
|
451
|
+
};
|
|
452
|
+
return updateTransform(newTransform);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
function panRight(canvas, config, updateTransform) {
|
|
456
|
+
const panDistance = config.keyboardPanStep;
|
|
457
|
+
const newTransform = {
|
|
458
|
+
translateX: canvas.transform.translateX - panDistance,
|
|
459
|
+
};
|
|
460
|
+
return updateTransform(newTransform);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
function panUp(canvas, config, updateTransform) {
|
|
464
|
+
const panDistance = config.keyboardPanStep;
|
|
465
|
+
const newTransform = {
|
|
466
|
+
translateY: canvas.transform.translateY + panDistance,
|
|
467
|
+
};
|
|
468
|
+
return updateTransform(newTransform);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function scrollToPoint(canvas, config, x, y, updateTransform, transformLayer) {
|
|
472
|
+
return withTransition(transformLayer, config, () => {
|
|
473
|
+
const bounds = getCanvasBounds(canvas, config);
|
|
474
|
+
const centerX = bounds.width / 2;
|
|
475
|
+
const centerY = bounds.height / 2;
|
|
476
|
+
// Calculate new translation to center the point
|
|
477
|
+
const newTranslateX = centerX - x * canvas.transform.scale;
|
|
478
|
+
const newTranslateY = centerY - y * canvas.transform.scale;
|
|
479
|
+
return updateTransform({
|
|
480
|
+
translateX: newTranslateX,
|
|
481
|
+
translateY: newTranslateY,
|
|
482
|
+
});
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
|
|
429
486
|
function createMatrixString(matrix) {
|
|
430
487
|
return `matrix3d(${matrix.m11}, ${matrix.m12}, ${matrix.m13}, ${matrix.m14}, ${matrix.m21}, ${matrix.m22}, ${matrix.m23}, ${matrix.m24}, ${matrix.m31}, ${matrix.m32}, ${matrix.m33}, ${matrix.m34}, ${matrix.m41}, ${matrix.m42}, ${matrix.m43}, ${matrix.m44})`;
|
|
431
488
|
}
|
|
@@ -457,136 +514,296 @@ function enableHardwareAcceleration(element) {
|
|
|
457
514
|
}
|
|
458
515
|
}
|
|
459
516
|
|
|
460
|
-
function
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
517
|
+
function updateTransform(canvas, newTransform) {
|
|
518
|
+
canvas.transform = { ...canvas.transform, ...newTransform };
|
|
519
|
+
const matrix = createMatrix(canvas.transform.scale, canvas.transform.translateX, canvas.transform.translateY);
|
|
520
|
+
return applyTransform(canvas.transformLayer, matrix);
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
function resetTransform(canvas) {
|
|
524
|
+
const resetTransformData = {
|
|
525
|
+
scale: 1.0,
|
|
526
|
+
translateX: 0,
|
|
527
|
+
translateY: 0,
|
|
528
|
+
};
|
|
529
|
+
return updateTransform(canvas, resetTransformData);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function hideGrid(rulers) {
|
|
533
|
+
if (rulers?.gridOverlay) {
|
|
534
|
+
rulers.gridOverlay.style.display = "none";
|
|
535
|
+
return true;
|
|
475
536
|
}
|
|
476
|
-
|
|
477
|
-
|
|
537
|
+
return false;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
function isGridVisible(rulers) {
|
|
541
|
+
if (rulers?.gridOverlay) {
|
|
542
|
+
return rulers.gridOverlay.style.display !== "none";
|
|
543
|
+
}
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
function showGrid(rulers) {
|
|
548
|
+
if (rulers?.gridOverlay) {
|
|
549
|
+
rulers.gridOverlay.style.display = "block";
|
|
478
550
|
return true;
|
|
479
551
|
}
|
|
552
|
+
return false;
|
|
480
553
|
}
|
|
481
554
|
|
|
482
|
-
function
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
555
|
+
function toggleGrid(rulers) {
|
|
556
|
+
if (rulers?.toggleGrid) {
|
|
557
|
+
rulers.toggleGrid();
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
return false;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
function areRulersVisible(rulers) {
|
|
564
|
+
if (rulers?.horizontalRuler) {
|
|
565
|
+
return rulers.horizontalRuler.style.display !== "none";
|
|
566
|
+
}
|
|
567
|
+
return false;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
function hideRulers(rulers) {
|
|
571
|
+
if (rulers) {
|
|
572
|
+
rulers.hide();
|
|
573
|
+
return true;
|
|
574
|
+
}
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
function showRulers(rulers) {
|
|
579
|
+
if (rulers) {
|
|
580
|
+
rulers.show();
|
|
581
|
+
return true;
|
|
582
|
+
}
|
|
583
|
+
return false;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
function toggleRulers(rulers, areRulersVisible) {
|
|
587
|
+
if (rulers) {
|
|
588
|
+
const isVisible = areRulersVisible();
|
|
589
|
+
if (isVisible) {
|
|
590
|
+
rulers.hide();
|
|
491
591
|
}
|
|
492
|
-
|
|
592
|
+
else {
|
|
593
|
+
rulers.show();
|
|
594
|
+
}
|
|
595
|
+
return true;
|
|
596
|
+
}
|
|
597
|
+
return false;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
function toggleTransition(enableTransition) {
|
|
601
|
+
return !enableTransition;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
function createMarkupCanvasConfig(options = {}) {
|
|
605
|
+
const config = {
|
|
606
|
+
...DEFAULT_CONFIG,
|
|
607
|
+
...options,
|
|
608
|
+
};
|
|
609
|
+
if (typeof config.width !== "number" || config.width <= 0) {
|
|
610
|
+
console.warn("Invalid width, using default");
|
|
611
|
+
config.width = DEFAULT_CONFIG.width;
|
|
612
|
+
}
|
|
613
|
+
if (typeof config.height !== "number" || config.height <= 0) {
|
|
614
|
+
console.warn("Invalid height, using default");
|
|
615
|
+
config.height = DEFAULT_CONFIG.height;
|
|
616
|
+
}
|
|
617
|
+
if (typeof config.zoomSpeed !== "number" || config.zoomSpeed <= 0) {
|
|
618
|
+
console.warn("Invalid zoomSpeed, using default");
|
|
619
|
+
config.zoomSpeed = DEFAULT_CONFIG.zoomSpeed;
|
|
620
|
+
}
|
|
621
|
+
if (typeof config.minZoom !== "number" || config.minZoom <= 0) {
|
|
622
|
+
console.warn("Invalid minZoom, using default");
|
|
623
|
+
config.minZoom = DEFAULT_CONFIG.minZoom;
|
|
624
|
+
}
|
|
625
|
+
if (typeof config.maxZoom !== "number" || config.maxZoom <= config.minZoom) {
|
|
626
|
+
console.warn("Invalid maxZoom, using default");
|
|
627
|
+
config.maxZoom = DEFAULT_CONFIG.maxZoom;
|
|
628
|
+
}
|
|
629
|
+
if (typeof config.keyboardPanStep !== "number" || config.keyboardPanStep <= 0) {
|
|
630
|
+
console.warn("Invalid keyboardPanStep, using default");
|
|
631
|
+
config.keyboardPanStep = DEFAULT_CONFIG.keyboardPanStep;
|
|
632
|
+
}
|
|
633
|
+
if (typeof config.keyboardFastMultiplier !== "number" || config.keyboardFastMultiplier <= 0) {
|
|
634
|
+
console.warn("Invalid keyboardFastMultiplier, using default");
|
|
635
|
+
config.keyboardFastMultiplier = DEFAULT_CONFIG.keyboardFastMultiplier;
|
|
636
|
+
}
|
|
637
|
+
if (typeof config.clickZoomLevel !== "number" || config.clickZoomLevel <= 0) {
|
|
638
|
+
console.warn("Invalid clickZoomLevel, using default");
|
|
639
|
+
config.clickZoomLevel = DEFAULT_CONFIG.clickZoomLevel;
|
|
640
|
+
}
|
|
641
|
+
if (typeof config.rulerFontSize !== "number" || config.rulerFontSize <= 0) {
|
|
642
|
+
console.warn("Invalid rulerFontSize, using default");
|
|
643
|
+
config.rulerFontSize = DEFAULT_CONFIG.rulerFontSize;
|
|
644
|
+
}
|
|
645
|
+
if (typeof config.rulerSize !== "number" || config.rulerSize <= 0) {
|
|
646
|
+
console.warn("Invalid rulerSize, using default");
|
|
647
|
+
config.rulerSize = DEFAULT_CONFIG.rulerSize;
|
|
648
|
+
}
|
|
649
|
+
return config;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
function updateThemeMode(canvasContainer, config, rulers, mode) {
|
|
653
|
+
const newConfig = {
|
|
654
|
+
...config,
|
|
655
|
+
themeMode: mode,
|
|
656
|
+
};
|
|
657
|
+
const updatedConfig = createMarkupCanvasConfig(newConfig);
|
|
658
|
+
// Update canvas background color
|
|
659
|
+
const backgroundColor = getThemeValue(updatedConfig, "canvasBackgroundColor");
|
|
660
|
+
canvasContainer.style.backgroundColor = backgroundColor;
|
|
661
|
+
// Update rulers if they exist
|
|
662
|
+
if (rulers) {
|
|
663
|
+
rulers.updateTheme(updatedConfig);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
function resetView(canvas, transformLayer, config) {
|
|
668
|
+
return withTransition(transformLayer, config, () => {
|
|
669
|
+
return withRulerSize(canvas, config.rulerSize, (rulerSize) => {
|
|
670
|
+
const resetTransformData = {
|
|
671
|
+
scale: 1.0,
|
|
672
|
+
translateX: rulerSize * -1,
|
|
673
|
+
translateY: rulerSize * -1,
|
|
674
|
+
};
|
|
675
|
+
return updateTransform(canvas, resetTransformData);
|
|
676
|
+
});
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
function getViewportCenter(canvas) {
|
|
681
|
+
try {
|
|
682
|
+
const bounds = canvas.getBounds();
|
|
683
|
+
return {
|
|
684
|
+
x: bounds.width / 2,
|
|
685
|
+
y: bounds.height / 2,
|
|
686
|
+
};
|
|
493
687
|
}
|
|
494
688
|
catch (error) {
|
|
495
|
-
console.
|
|
496
|
-
return
|
|
689
|
+
console.warn("Failed to calculate viewport center:", error);
|
|
690
|
+
return { x: 0, y: 0 };
|
|
497
691
|
}
|
|
498
692
|
}
|
|
499
693
|
|
|
500
|
-
function
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
694
|
+
function resetViewToCenter(canvas, transformLayer, config, zoomToPoint) {
|
|
695
|
+
return withTransition(transformLayer, config, () => {
|
|
696
|
+
return withClampedZoom(config, (clamp) => {
|
|
697
|
+
const newScale = clamp(1.0);
|
|
698
|
+
const center = getViewportCenter(canvas);
|
|
699
|
+
return zoomToPoint(center.x, center.y, newScale);
|
|
700
|
+
});
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
function setZoom(canvas, transformLayer, config, zoomToPoint, zoomLevel) {
|
|
705
|
+
return withTransition(transformLayer, config, () => {
|
|
706
|
+
return withClampedZoom(config, (clamp) => {
|
|
707
|
+
const newScale = clamp(zoomLevel);
|
|
708
|
+
const center = getViewportCenter(canvas);
|
|
709
|
+
return zoomToPoint(center.x, center.y, newScale);
|
|
710
|
+
});
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
function zoomIn(canvas, transformLayer, config, zoomToPoint, factor = 0.5) {
|
|
715
|
+
return withTransition(transformLayer, config, () => {
|
|
716
|
+
return withClampedZoom(config, (clamp) => {
|
|
717
|
+
const newScale = clamp(canvas.transform.scale * (1 + factor));
|
|
718
|
+
const center = getViewportCenter(canvas);
|
|
719
|
+
return zoomToPoint(center.x, center.y, newScale);
|
|
720
|
+
});
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
function zoomOut(canvas, transformLayer, config, zoomToPoint, factor = 0.5) {
|
|
725
|
+
return withTransition(transformLayer, config, () => {
|
|
726
|
+
return withClampedZoom(config, (clamp) => {
|
|
727
|
+
const newScale = clamp(canvas.transform.scale * (1 - factor));
|
|
728
|
+
const center = getViewportCenter(canvas);
|
|
729
|
+
return zoomToPoint(center.x, center.y, newScale);
|
|
730
|
+
});
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
function zoomToPoint(canvas, transformLayer, config, x, y, targetScale) {
|
|
735
|
+
return withTransition(transformLayer, config, () => {
|
|
736
|
+
const newTransform = getZoomToMouseTransform(x, y, canvas.transform, targetScale / canvas.transform.scale, config);
|
|
737
|
+
return updateTransform(canvas, newTransform);
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
function fitToScreen(canvas, transformLayer, config) {
|
|
742
|
+
return withTransition(transformLayer, config, () => {
|
|
743
|
+
const bounds = getCanvasBounds(canvas, config);
|
|
744
|
+
const scaleX = bounds.width / config.width;
|
|
745
|
+
const scaleY = bounds.height / config.height;
|
|
746
|
+
const fitScale = withClampedZoom(config, (clamp) => clamp(Math.min(scaleX, scaleY) * ZOOM_FIT_PADDING));
|
|
747
|
+
// Center the content
|
|
748
|
+
const scaledWidth = config.width * fitScale;
|
|
749
|
+
const scaledHeight = config.height * fitScale;
|
|
750
|
+
const centerX = (bounds.width - scaledWidth) / 2;
|
|
751
|
+
const centerY = (bounds.height - scaledHeight) / 2;
|
|
752
|
+
return updateTransform(canvas, {
|
|
753
|
+
scale: fitScale,
|
|
754
|
+
translateX: centerX,
|
|
755
|
+
translateY: centerY,
|
|
756
|
+
});
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
function moveExistingContent(existingContent, contentLayer, transformLayer) {
|
|
761
|
+
existingContent.forEach((child) => {
|
|
762
|
+
if (child !== transformLayer && !child.classList.contains(TRANSFORM_LAYER_CLASS)) {
|
|
763
|
+
contentLayer.appendChild(child);
|
|
764
|
+
}
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
function setupContentLayer(contentLayer) {
|
|
769
|
+
contentLayer.style.position = "relative";
|
|
770
|
+
contentLayer.style.width = "100%";
|
|
771
|
+
contentLayer.style.height = "100%";
|
|
772
|
+
contentLayer.style.pointerEvents = "auto";
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// Sets up the transform layer with proper styles and dimensions
|
|
776
|
+
function setupTransformLayer(transformLayer, config) {
|
|
777
|
+
transformLayer.style.position = "absolute";
|
|
778
|
+
const rulerOffset = config.rulerSize;
|
|
779
|
+
transformLayer.style.top = `${rulerOffset}px`;
|
|
780
|
+
transformLayer.style.left = `${rulerOffset}px`;
|
|
781
|
+
transformLayer.style.width = `${config.width}px`;
|
|
782
|
+
transformLayer.style.height = `${config.height}px`;
|
|
783
|
+
transformLayer.style.transformOrigin = "0 0";
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
function createCanvasLayers(container, config) {
|
|
787
|
+
const existingContent = Array.from(container.children);
|
|
788
|
+
// Create or find transform layer
|
|
789
|
+
let transformLayer = container.querySelector(`.${TRANSFORM_LAYER_CLASS}`);
|
|
790
|
+
if (!transformLayer) {
|
|
791
|
+
transformLayer = document.createElement("div");
|
|
792
|
+
transformLayer.className = TRANSFORM_LAYER_CLASS;
|
|
793
|
+
container.appendChild(transformLayer);
|
|
505
794
|
}
|
|
506
|
-
|
|
507
|
-
|
|
795
|
+
setupTransformLayer(transformLayer, config);
|
|
796
|
+
// Create or find content layer
|
|
797
|
+
let contentLayer = transformLayer.querySelector(`.${CONTENT_LAYER_CLASS}`);
|
|
798
|
+
if (!contentLayer) {
|
|
799
|
+
contentLayer = document.createElement("div");
|
|
800
|
+
contentLayer.className = CONTENT_LAYER_CLASS;
|
|
801
|
+
transformLayer.appendChild(contentLayer);
|
|
802
|
+
moveExistingContent(existingContent, contentLayer, transformLayer);
|
|
508
803
|
}
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
return {
|
|
513
|
-
// Utility methods
|
|
514
|
-
getBounds: function () {
|
|
515
|
-
return getCanvasBounds(this);
|
|
516
|
-
},
|
|
517
|
-
// Transform methods
|
|
518
|
-
updateTransform: function (newTransform) {
|
|
519
|
-
this.transform = { ...this.transform, ...newTransform };
|
|
520
|
-
const matrix = createMatrix(this.transform.scale, this.transform.translateX, this.transform.translateY);
|
|
521
|
-
const result = applyTransform(this.transformLayer, matrix);
|
|
522
|
-
withFeatureEnabled(this.config, "onTransformUpdate", () => {
|
|
523
|
-
this.config.onTransformUpdate(this.transform);
|
|
524
|
-
});
|
|
525
|
-
return result;
|
|
526
|
-
},
|
|
527
|
-
// Reset method
|
|
528
|
-
reset: function () {
|
|
529
|
-
const resetTransform = {
|
|
530
|
-
scale: 1.0,
|
|
531
|
-
translateX: 0,
|
|
532
|
-
translateY: 0,
|
|
533
|
-
};
|
|
534
|
-
return this.updateTransform(resetTransform);
|
|
535
|
-
},
|
|
536
|
-
// Handle canvas resize
|
|
537
|
-
handleResize: function () {
|
|
538
|
-
return true;
|
|
539
|
-
},
|
|
540
|
-
// Set zoom level
|
|
541
|
-
setZoom: function (zoomLevel) {
|
|
542
|
-
const newScale = withClampedZoom(this.config, (clamp) => clamp(zoomLevel));
|
|
543
|
-
return this.updateTransform({ scale: newScale });
|
|
544
|
-
},
|
|
545
|
-
// Convert canvas coordinates to content coordinates
|
|
546
|
-
canvasToContent: function (x, y) {
|
|
547
|
-
const matrix = createMatrix(this.transform.scale, this.transform.translateX, this.transform.translateY);
|
|
548
|
-
return canvasToContent(x, y, matrix);
|
|
549
|
-
},
|
|
550
|
-
// Zoom to a specific point with animation
|
|
551
|
-
zoomToPoint: function (x, y, targetScale) {
|
|
552
|
-
return withTransition(this.transformLayer, this.config, () => {
|
|
553
|
-
const newTransform = getZoomToMouseTransform(x, y, this.transform, targetScale / this.transform.scale, this.config);
|
|
554
|
-
return this.updateTransform(newTransform);
|
|
555
|
-
});
|
|
556
|
-
},
|
|
557
|
-
// Reset view with animation
|
|
558
|
-
resetView: function () {
|
|
559
|
-
return withTransition(this.transformLayer, this.config, () => {
|
|
560
|
-
return withRulerSize(this, this.config.rulerSize, (rulerSize) => {
|
|
561
|
-
const resetTransform = {
|
|
562
|
-
scale: 1.0,
|
|
563
|
-
translateX: rulerSize * -1,
|
|
564
|
-
translateY: rulerSize * -1,
|
|
565
|
-
};
|
|
566
|
-
return this.updateTransform(resetTransform);
|
|
567
|
-
});
|
|
568
|
-
});
|
|
569
|
-
},
|
|
570
|
-
// Zoom to fit content in canvas
|
|
571
|
-
zoomToFitContent: function () {
|
|
572
|
-
return withTransition(this.transformLayer, this.config, () => {
|
|
573
|
-
const bounds = this.getBounds();
|
|
574
|
-
const scaleX = bounds.width / this.config.width;
|
|
575
|
-
const scaleY = bounds.height / this.config.height;
|
|
576
|
-
const fitScale = withClampedZoom(this.config, (clamp) => clamp(Math.min(scaleX, scaleY) * ZOOM_FIT_PADDING));
|
|
577
|
-
// Center the content
|
|
578
|
-
const scaledWidth = this.config.width * fitScale;
|
|
579
|
-
const scaledHeight = this.config.height * fitScale;
|
|
580
|
-
const centerX = (bounds.width - scaledWidth) / 2;
|
|
581
|
-
const centerY = (bounds.height - scaledHeight) / 2;
|
|
582
|
-
return this.updateTransform({
|
|
583
|
-
scale: fitScale,
|
|
584
|
-
translateX: centerX,
|
|
585
|
-
translateY: centerY,
|
|
586
|
-
});
|
|
587
|
-
});
|
|
588
|
-
},
|
|
589
|
-
};
|
|
804
|
+
// Set content layer properties
|
|
805
|
+
setupContentLayer(contentLayer);
|
|
806
|
+
return { transformLayer, contentLayer };
|
|
590
807
|
}
|
|
591
808
|
|
|
592
809
|
function checkContainerDimensions(container) {
|
|
@@ -622,7 +839,6 @@ function setupCanvasContainer(container, config) {
|
|
|
622
839
|
}
|
|
623
840
|
}
|
|
624
841
|
|
|
625
|
-
// Creates and initializes a canvas with the required DOM structure
|
|
626
842
|
function createCanvas(container, config) {
|
|
627
843
|
if (!container?.appendChild) {
|
|
628
844
|
console.error("Invalid container element provided to createCanvas");
|
|
@@ -631,10 +847,9 @@ function createCanvas(container, config) {
|
|
|
631
847
|
try {
|
|
632
848
|
setupCanvasContainer(container, config);
|
|
633
849
|
const { transformLayer, contentLayer } = createCanvasLayers(container, config);
|
|
634
|
-
|
|
635
|
-
if (config.enableAcceleration) {
|
|
850
|
+
withFeatureEnabled(config, "enableAcceleration", () => {
|
|
636
851
|
enableHardwareAcceleration(transformLayer);
|
|
637
|
-
}
|
|
852
|
+
});
|
|
638
853
|
const rulerOffset = config.enableRulers ? -config.rulerSize : 0;
|
|
639
854
|
const initialTransform = {
|
|
640
855
|
scale: DEFAULT_ZOOM,
|
|
@@ -649,12 +864,8 @@ function createCanvas(container, config) {
|
|
|
649
864
|
container,
|
|
650
865
|
transformLayer,
|
|
651
866
|
contentLayer,
|
|
652
|
-
// Configuration
|
|
653
|
-
config: config,
|
|
654
867
|
// Current state
|
|
655
868
|
transform: initialTransform,
|
|
656
|
-
// Add all canvas methods
|
|
657
|
-
...getCanvasMethods(),
|
|
658
869
|
};
|
|
659
870
|
return canvas;
|
|
660
871
|
}
|
|
@@ -664,54 +875,6 @@ function createCanvas(container, config) {
|
|
|
664
875
|
}
|
|
665
876
|
}
|
|
666
877
|
|
|
667
|
-
function createMarkupCanvasConfig(options = {}) {
|
|
668
|
-
const config = {
|
|
669
|
-
...DEFAULT_CONFIG,
|
|
670
|
-
...options,
|
|
671
|
-
};
|
|
672
|
-
if (typeof config.width !== "number" || config.width <= 0) {
|
|
673
|
-
console.warn("Invalid width, using default");
|
|
674
|
-
config.width = DEFAULT_CONFIG.width;
|
|
675
|
-
}
|
|
676
|
-
if (typeof config.height !== "number" || config.height <= 0) {
|
|
677
|
-
console.warn("Invalid height, using default");
|
|
678
|
-
config.height = DEFAULT_CONFIG.height;
|
|
679
|
-
}
|
|
680
|
-
if (typeof config.zoomSpeed !== "number" || config.zoomSpeed <= 0) {
|
|
681
|
-
console.warn("Invalid zoomSpeed, using default");
|
|
682
|
-
config.zoomSpeed = DEFAULT_CONFIG.zoomSpeed;
|
|
683
|
-
}
|
|
684
|
-
if (typeof config.minZoom !== "number" || config.minZoom <= 0) {
|
|
685
|
-
console.warn("Invalid minZoom, using default");
|
|
686
|
-
config.minZoom = DEFAULT_CONFIG.minZoom;
|
|
687
|
-
}
|
|
688
|
-
if (typeof config.maxZoom !== "number" || config.maxZoom <= config.minZoom) {
|
|
689
|
-
console.warn("Invalid maxZoom, using default");
|
|
690
|
-
config.maxZoom = DEFAULT_CONFIG.maxZoom;
|
|
691
|
-
}
|
|
692
|
-
if (typeof config.keyboardPanStep !== "number" || config.keyboardPanStep <= 0) {
|
|
693
|
-
console.warn("Invalid keyboardPanStep, using default");
|
|
694
|
-
config.keyboardPanStep = DEFAULT_CONFIG.keyboardPanStep;
|
|
695
|
-
}
|
|
696
|
-
if (typeof config.keyboardFastMultiplier !== "number" || config.keyboardFastMultiplier <= 0) {
|
|
697
|
-
console.warn("Invalid keyboardFastMultiplier, using default");
|
|
698
|
-
config.keyboardFastMultiplier = DEFAULT_CONFIG.keyboardFastMultiplier;
|
|
699
|
-
}
|
|
700
|
-
if (typeof config.clickZoomLevel !== "number" || config.clickZoomLevel <= 0) {
|
|
701
|
-
console.warn("Invalid clickZoomLevel, using default");
|
|
702
|
-
config.clickZoomLevel = DEFAULT_CONFIG.clickZoomLevel;
|
|
703
|
-
}
|
|
704
|
-
if (typeof config.rulerFontSize !== "number" || config.rulerFontSize <= 0) {
|
|
705
|
-
console.warn("Invalid rulerFontSize, using default");
|
|
706
|
-
config.rulerFontSize = DEFAULT_CONFIG.rulerFontSize;
|
|
707
|
-
}
|
|
708
|
-
if (typeof config.rulerSize !== "number" || config.rulerSize <= 0) {
|
|
709
|
-
console.warn("Invalid rulerSize, using default");
|
|
710
|
-
config.rulerSize = DEFAULT_CONFIG.rulerSize;
|
|
711
|
-
}
|
|
712
|
-
return config;
|
|
713
|
-
}
|
|
714
|
-
|
|
715
878
|
class EventEmitter {
|
|
716
879
|
constructor() {
|
|
717
880
|
this.listeners = new Map();
|
|
@@ -750,6 +913,13 @@ class EventEmitter {
|
|
|
750
913
|
}
|
|
751
914
|
}
|
|
752
915
|
|
|
916
|
+
function emitTransformEvents(listen, canvas) {
|
|
917
|
+
const transform = canvas.transform;
|
|
918
|
+
listen.emit("transform", transform);
|
|
919
|
+
listen.emit("zoom", transform.scale);
|
|
920
|
+
listen.emit("pan", { x: transform.translateX, y: transform.translateY });
|
|
921
|
+
}
|
|
922
|
+
|
|
753
923
|
const REFERENCE_DISPLAY_AREA = 1920 * 1080;
|
|
754
924
|
const TRACKPAD_PINCH_SPEED_FACTOR = 0.05;
|
|
755
925
|
const ADAPTIVE_ZOOM_FACTOR = 1;
|
|
@@ -776,42 +946,28 @@ function getAdaptiveZoomSpeed(canvas, baseSpeed) {
|
|
|
776
946
|
}
|
|
777
947
|
|
|
778
948
|
function setupKeyboardEvents(canvas, config) {
|
|
779
|
-
// Track mouse position
|
|
780
|
-
let lastMouseX = 0;
|
|
781
|
-
let lastMouseY = 0;
|
|
782
|
-
function handleMouseMove(event) {
|
|
783
|
-
const rect = canvas.container.getBoundingClientRect();
|
|
784
|
-
const rawMouseX = event.clientX - rect.left;
|
|
785
|
-
const rawMouseY = event.clientY - rect.top;
|
|
786
|
-
withRulerOffsets(canvas, config.rulerSize, rawMouseX, rawMouseY, (adjustedX, adjustedY) => {
|
|
787
|
-
lastMouseX = adjustedX;
|
|
788
|
-
lastMouseY = adjustedY;
|
|
789
|
-
});
|
|
790
|
-
}
|
|
791
949
|
function handleKeyDown(event) {
|
|
792
950
|
if (!(event instanceof KeyboardEvent))
|
|
793
951
|
return;
|
|
794
952
|
if (config.bindKeyboardEventsTo === "canvas" && document.activeElement !== canvas.container)
|
|
795
953
|
return;
|
|
796
|
-
const isFastPan = event.shiftKey;
|
|
797
|
-
const panDistance = config.keyboardPanStep * (isFastPan ? config.keyboardFastMultiplier : 1);
|
|
798
954
|
let handled = false;
|
|
799
955
|
const newTransform = {};
|
|
800
956
|
switch (event.key) {
|
|
801
957
|
case "ArrowLeft":
|
|
802
|
-
newTransform.translateX = canvas.transform.translateX +
|
|
958
|
+
newTransform.translateX = canvas.transform.translateX + config.keyboardPanStep;
|
|
803
959
|
handled = true;
|
|
804
960
|
break;
|
|
805
961
|
case "ArrowRight":
|
|
806
|
-
newTransform.translateX = canvas.transform.translateX -
|
|
962
|
+
newTransform.translateX = canvas.transform.translateX - config.keyboardPanStep;
|
|
807
963
|
handled = true;
|
|
808
964
|
break;
|
|
809
965
|
case "ArrowUp":
|
|
810
|
-
newTransform.translateY = canvas.transform.translateY +
|
|
966
|
+
newTransform.translateY = canvas.transform.translateY + config.keyboardPanStep;
|
|
811
967
|
handled = true;
|
|
812
968
|
break;
|
|
813
969
|
case "ArrowDown":
|
|
814
|
-
newTransform.translateY = canvas.transform.translateY -
|
|
970
|
+
newTransform.translateY = canvas.transform.translateY - config.keyboardPanStep;
|
|
815
971
|
handled = true;
|
|
816
972
|
break;
|
|
817
973
|
case "=":
|
|
@@ -820,7 +976,7 @@ function setupKeyboardEvents(canvas, config) {
|
|
|
820
976
|
const adaptiveZoomStep = config.enableAdaptiveSpeed
|
|
821
977
|
? getAdaptiveZoomSpeed(canvas, config.keyboardZoomStep)
|
|
822
978
|
: config.keyboardZoomStep;
|
|
823
|
-
|
|
979
|
+
canvas.zoomIn(adaptiveZoomStep);
|
|
824
980
|
handled = true;
|
|
825
981
|
}
|
|
826
982
|
break;
|
|
@@ -829,16 +985,21 @@ function setupKeyboardEvents(canvas, config) {
|
|
|
829
985
|
const adaptiveZoomStep = config.enableAdaptiveSpeed
|
|
830
986
|
? getAdaptiveZoomSpeed(canvas, config.keyboardZoomStep)
|
|
831
987
|
: config.keyboardZoomStep;
|
|
832
|
-
|
|
988
|
+
canvas.zoomOut(adaptiveZoomStep);
|
|
833
989
|
handled = true;
|
|
834
990
|
}
|
|
835
991
|
break;
|
|
836
992
|
case "0":
|
|
837
|
-
if (event.
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
993
|
+
if (event.ctrlKey) {
|
|
994
|
+
if (canvas.resetView) {
|
|
995
|
+
canvas.resetView();
|
|
996
|
+
}
|
|
997
|
+
handled = true;
|
|
998
|
+
}
|
|
999
|
+
else if (event.metaKey || event.ctrlKey) {
|
|
1000
|
+
if (canvas.resetViewToCenter) {
|
|
1001
|
+
canvas.resetViewToCenter();
|
|
1002
|
+
}
|
|
842
1003
|
handled = true;
|
|
843
1004
|
}
|
|
844
1005
|
break;
|
|
@@ -866,10 +1027,8 @@ function setupKeyboardEvents(canvas, config) {
|
|
|
866
1027
|
}
|
|
867
1028
|
const keyboardTarget = config.bindKeyboardEventsTo === "canvas" ? canvas.container : document;
|
|
868
1029
|
keyboardTarget.addEventListener("keydown", handleKeyDown);
|
|
869
|
-
canvas.container.addEventListener("mousemove", handleMouseMove);
|
|
870
1030
|
return () => {
|
|
871
1031
|
keyboardTarget.removeEventListener("keydown", handleKeyDown);
|
|
872
|
-
canvas.container.removeEventListener("mousemove", handleMouseMove);
|
|
873
1032
|
};
|
|
874
1033
|
}
|
|
875
1034
|
|
|
@@ -1255,6 +1414,17 @@ function setupPostMessageEvents(canvas) {
|
|
|
1255
1414
|
const newMode = currentConfig.themeMode === "light" ? "dark" : "light";
|
|
1256
1415
|
canvas.updateThemeMode(newMode);
|
|
1257
1416
|
}
|
|
1417
|
+
// Transition methods
|
|
1418
|
+
else if (action === "updateTransition") {
|
|
1419
|
+
const enabled = args[0];
|
|
1420
|
+
if (typeof enabled !== "boolean") {
|
|
1421
|
+
throw new Error(`Invalid transition enabled value: ${enabled}. Must be a boolean.`);
|
|
1422
|
+
}
|
|
1423
|
+
canvas.updateTransition(enabled);
|
|
1424
|
+
}
|
|
1425
|
+
else if (action === "toggleTransitionMode") {
|
|
1426
|
+
canvas.toggleTransitionMode();
|
|
1427
|
+
}
|
|
1258
1428
|
else {
|
|
1259
1429
|
throw new Error(`Unknown action: ${action}`);
|
|
1260
1430
|
}
|
|
@@ -1852,8 +2022,6 @@ function createRulers(canvas, config) {
|
|
|
1852
2022
|
elements.verticalRuler.style.display = "block";
|
|
1853
2023
|
if (elements.cornerBox)
|
|
1854
2024
|
elements.cornerBox.style.display = "flex";
|
|
1855
|
-
if (elements.gridOverlay)
|
|
1856
|
-
elements.gridOverlay.style.display = "block";
|
|
1857
2025
|
},
|
|
1858
2026
|
hide: () => {
|
|
1859
2027
|
if (elements.horizontalRuler)
|
|
@@ -1897,14 +2065,163 @@ function createRulers(canvas, config) {
|
|
|
1897
2065
|
}
|
|
1898
2066
|
}
|
|
1899
2067
|
|
|
2068
|
+
function broadcastEvent(event, data, config) {
|
|
2069
|
+
if (typeof window === "undefined") {
|
|
2070
|
+
return;
|
|
2071
|
+
}
|
|
2072
|
+
// Receivers can get the instance from the window binding
|
|
2073
|
+
let broadcastData = data;
|
|
2074
|
+
if (event === "ready") {
|
|
2075
|
+
broadcastData = { ready: true };
|
|
2076
|
+
}
|
|
2077
|
+
window.postMessage({
|
|
2078
|
+
source: "markup-canvas",
|
|
2079
|
+
event,
|
|
2080
|
+
data: broadcastData,
|
|
2081
|
+
timestamp: Date.now(),
|
|
2082
|
+
canvasName: config.name,
|
|
2083
|
+
}, "*");
|
|
2084
|
+
if (window.parent) {
|
|
2085
|
+
window.parent.postMessage({
|
|
2086
|
+
source: "markup-canvas",
|
|
2087
|
+
event,
|
|
2088
|
+
data: broadcastData,
|
|
2089
|
+
timestamp: Date.now(),
|
|
2090
|
+
canvasName: config.name,
|
|
2091
|
+
}, "*");
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
function cleanupWindowBinding(config) {
|
|
2096
|
+
if (typeof window === "undefined") {
|
|
2097
|
+
return;
|
|
2098
|
+
}
|
|
2099
|
+
const canvasName = config.name || "markupCanvas";
|
|
2100
|
+
const windowObj = window;
|
|
2101
|
+
delete windowObj[canvasName];
|
|
2102
|
+
if (windowObj.__markupCanvasInstances) {
|
|
2103
|
+
windowObj.__markupCanvasInstances.delete(canvasName);
|
|
2104
|
+
}
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
function bindCanvasToWindow(canvas, config) {
|
|
2108
|
+
if (typeof window === "undefined") {
|
|
2109
|
+
return;
|
|
2110
|
+
}
|
|
2111
|
+
const canvasName = config.name || "markupCanvas";
|
|
2112
|
+
const windowObj = window;
|
|
2113
|
+
const api = {
|
|
2114
|
+
config: {
|
|
2115
|
+
get current() {
|
|
2116
|
+
return canvas.config;
|
|
2117
|
+
},
|
|
2118
|
+
get: canvas.getConfig.bind(canvas),
|
|
2119
|
+
update: canvas.updateConfig.bind(canvas),
|
|
2120
|
+
},
|
|
2121
|
+
// Transform group
|
|
2122
|
+
transform: {
|
|
2123
|
+
update: canvas.updateTransform.bind(canvas),
|
|
2124
|
+
reset: canvas.reset.bind(canvas),
|
|
2125
|
+
},
|
|
2126
|
+
// Zoom group
|
|
2127
|
+
zoom: {
|
|
2128
|
+
set: canvas.setZoom.bind(canvas),
|
|
2129
|
+
toPoint: canvas.zoomToPoint.bind(canvas),
|
|
2130
|
+
in: canvas.zoomIn.bind(canvas),
|
|
2131
|
+
out: canvas.zoomOut.bind(canvas),
|
|
2132
|
+
reset: canvas.resetZoom.bind(canvas),
|
|
2133
|
+
resetToCenter: canvas.resetViewToCenter.bind(canvas),
|
|
2134
|
+
fitToScreen: canvas.fitToScreen.bind(canvas),
|
|
2135
|
+
},
|
|
2136
|
+
// Pan group
|
|
2137
|
+
pan: {
|
|
2138
|
+
left: canvas.panLeft.bind(canvas),
|
|
2139
|
+
right: canvas.panRight.bind(canvas),
|
|
2140
|
+
up: canvas.panUp.bind(canvas),
|
|
2141
|
+
down: canvas.panDown.bind(canvas),
|
|
2142
|
+
toPoint: canvas.scrollToPoint.bind(canvas),
|
|
2143
|
+
toCenter: canvas.centerContent.bind(canvas),
|
|
2144
|
+
},
|
|
2145
|
+
// Mouse drag group
|
|
2146
|
+
mouseDrag: {
|
|
2147
|
+
enable: canvas.enableMouseDrag.bind(canvas),
|
|
2148
|
+
disable: canvas.disableMouseDrag.bind(canvas),
|
|
2149
|
+
isEnabled: canvas.isMouseDragEnabled.bind(canvas),
|
|
2150
|
+
},
|
|
2151
|
+
// Grid group
|
|
2152
|
+
grid: {
|
|
2153
|
+
toggle: canvas.toggleGrid.bind(canvas),
|
|
2154
|
+
show: canvas.showGrid.bind(canvas),
|
|
2155
|
+
hide: canvas.hideGrid.bind(canvas),
|
|
2156
|
+
isVisible: canvas.isGridVisible.bind(canvas),
|
|
2157
|
+
},
|
|
2158
|
+
// Ruler group
|
|
2159
|
+
rulers: {
|
|
2160
|
+
toggle: canvas.toggleRulers.bind(canvas),
|
|
2161
|
+
show: canvas.showRulers.bind(canvas),
|
|
2162
|
+
hide: canvas.hideRulers.bind(canvas),
|
|
2163
|
+
isVisible: canvas.areRulersVisible.bind(canvas),
|
|
2164
|
+
},
|
|
2165
|
+
// Utility group
|
|
2166
|
+
canvas: {
|
|
2167
|
+
canvasToContent: canvas.canvasToContent.bind(canvas),
|
|
2168
|
+
getVisibleArea: canvas.getVisibleArea.bind(canvas),
|
|
2169
|
+
isPointVisible: canvas.isPointVisible.bind(canvas),
|
|
2170
|
+
getBounds: canvas.getBounds.bind(canvas),
|
|
2171
|
+
},
|
|
2172
|
+
theme: {
|
|
2173
|
+
get current() {
|
|
2174
|
+
return canvas.config.themeMode;
|
|
2175
|
+
},
|
|
2176
|
+
update: canvas.updateThemeMode.bind(canvas),
|
|
2177
|
+
toggle: canvas.toggleThemeMode.bind(canvas),
|
|
2178
|
+
},
|
|
2179
|
+
transition: {
|
|
2180
|
+
get current() {
|
|
2181
|
+
return canvas.config.enableTransition;
|
|
2182
|
+
},
|
|
2183
|
+
set: canvas.updateTransition.bind(canvas),
|
|
2184
|
+
toggle: canvas.toggleTransitionMode.bind(canvas),
|
|
2185
|
+
},
|
|
2186
|
+
// Event group
|
|
2187
|
+
event: canvas.event,
|
|
2188
|
+
// Lifecycle group
|
|
2189
|
+
lifecycle: {
|
|
2190
|
+
cleanup: canvas.cleanup.bind(canvas),
|
|
2191
|
+
destroy: canvas.destroy.bind(canvas),
|
|
2192
|
+
},
|
|
2193
|
+
// Properties/State group
|
|
2194
|
+
state: {
|
|
2195
|
+
get isReady() {
|
|
2196
|
+
return canvas.isReady;
|
|
2197
|
+
},
|
|
2198
|
+
get isTransforming() {
|
|
2199
|
+
return canvas.isTransforming;
|
|
2200
|
+
},
|
|
2201
|
+
get visibleBounds() {
|
|
2202
|
+
return canvas.visibleBounds;
|
|
2203
|
+
},
|
|
2204
|
+
get transform() {
|
|
2205
|
+
return canvas.transform;
|
|
2206
|
+
},
|
|
2207
|
+
},
|
|
2208
|
+
};
|
|
2209
|
+
// Bind public API to window
|
|
2210
|
+
windowObj[canvasName] = api;
|
|
2211
|
+
// Track all instances
|
|
2212
|
+
if (!windowObj.__markupCanvasInstances) {
|
|
2213
|
+
windowObj.__markupCanvasInstances = new Map();
|
|
2214
|
+
}
|
|
2215
|
+
windowObj.__markupCanvasInstances.set(canvasName, api);
|
|
2216
|
+
}
|
|
2217
|
+
|
|
1900
2218
|
class MarkupCanvas {
|
|
1901
2219
|
constructor(container, options = {}) {
|
|
1902
|
-
this.
|
|
2220
|
+
this.cleanupCallbacks = [];
|
|
1903
2221
|
this.rulers = null;
|
|
1904
2222
|
this.dragSetup = null;
|
|
2223
|
+
this.event = new EventEmitter();
|
|
1905
2224
|
this._isReady = false;
|
|
1906
|
-
this.listen = new EventEmitter();
|
|
1907
|
-
this.postMessageCleanup = null;
|
|
1908
2225
|
if (!container) {
|
|
1909
2226
|
throw new Error("Container element is required");
|
|
1910
2227
|
}
|
|
@@ -1913,100 +2230,48 @@ class MarkupCanvas {
|
|
|
1913
2230
|
if (!canvas) {
|
|
1914
2231
|
throw new Error("Failed to create canvas");
|
|
1915
2232
|
}
|
|
1916
|
-
this.
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
2233
|
+
this.canvas = canvas;
|
|
2234
|
+
// Always bind canvas to window
|
|
2235
|
+
this.event.setEmitInterceptor((event, data) => {
|
|
2236
|
+
broadcastEvent(event, data, this.config);
|
|
2237
|
+
});
|
|
2238
|
+
bindCanvasToWindow(this, this.config);
|
|
2239
|
+
// Set up postMessage listener
|
|
2240
|
+
if (this.config.enablePostMessageAPI) {
|
|
2241
|
+
const postMessageCleanup = setupPostMessageEvents(this);
|
|
2242
|
+
this.cleanupCallbacks.push(postMessageCleanup);
|
|
1926
2243
|
}
|
|
1927
2244
|
this.setupEventHandlers();
|
|
1928
2245
|
this._isReady = true;
|
|
1929
2246
|
// Emit ready event
|
|
1930
|
-
this.
|
|
1931
|
-
}
|
|
1932
|
-
setupGlobalBinding() {
|
|
1933
|
-
if (typeof window === "undefined") {
|
|
1934
|
-
return;
|
|
1935
|
-
}
|
|
1936
|
-
const canvasName = this.config.name || "markupCanvas";
|
|
1937
|
-
const windowObj = window;
|
|
1938
|
-
// Bind instance to window
|
|
1939
|
-
windowObj[canvasName] = this;
|
|
1940
|
-
// Track all instances
|
|
1941
|
-
if (!windowObj.__markupCanvasInstances) {
|
|
1942
|
-
windowObj.__markupCanvasInstances = new Map();
|
|
1943
|
-
}
|
|
1944
|
-
windowObj.__markupCanvasInstances.set(canvasName, this);
|
|
1945
|
-
}
|
|
1946
|
-
cleanupGlobalBinding() {
|
|
1947
|
-
if (typeof window === "undefined") {
|
|
1948
|
-
return;
|
|
1949
|
-
}
|
|
1950
|
-
const canvasName = this.config.name || "markupCanvas";
|
|
1951
|
-
const windowObj = window;
|
|
1952
|
-
delete windowObj[canvasName];
|
|
1953
|
-
if (windowObj.__markupCanvasInstances) {
|
|
1954
|
-
windowObj.__markupCanvasInstances.delete(canvasName);
|
|
1955
|
-
}
|
|
1956
|
-
}
|
|
1957
|
-
broadcastEvent(event, data) {
|
|
1958
|
-
if (typeof window === "undefined") {
|
|
1959
|
-
return;
|
|
1960
|
-
}
|
|
1961
|
-
// Receivers can get the instance from the window binding
|
|
1962
|
-
let broadcastData = data;
|
|
1963
|
-
if (event === "ready") {
|
|
1964
|
-
broadcastData = { ready: true };
|
|
1965
|
-
}
|
|
1966
|
-
window.postMessage({
|
|
1967
|
-
source: "markup-canvas",
|
|
1968
|
-
event,
|
|
1969
|
-
data: broadcastData,
|
|
1970
|
-
timestamp: Date.now(),
|
|
1971
|
-
canvasName: this.config.name,
|
|
1972
|
-
}, "*");
|
|
1973
|
-
if (window.parent) {
|
|
1974
|
-
window.parent.postMessage({
|
|
1975
|
-
source: "markup-canvas",
|
|
1976
|
-
event,
|
|
1977
|
-
data: broadcastData,
|
|
1978
|
-
timestamp: Date.now(),
|
|
1979
|
-
canvasName: this.config.name,
|
|
1980
|
-
}, "*");
|
|
1981
|
-
}
|
|
2247
|
+
this.event.emit("ready", this);
|
|
1982
2248
|
}
|
|
1983
2249
|
setupEventHandlers() {
|
|
1984
2250
|
try {
|
|
1985
|
-
// Wheel
|
|
2251
|
+
// Wheel events
|
|
1986
2252
|
withFeatureEnabled(this.config, "enableZoom", () => {
|
|
1987
2253
|
const wheelCleanup = setupWheelEvents(this, this.config);
|
|
1988
|
-
this.
|
|
2254
|
+
this.cleanupCallbacks.push(wheelCleanup);
|
|
1989
2255
|
});
|
|
1990
|
-
// Mouse events
|
|
1991
|
-
// Set up mouse events if either pan or click-to-zoom is enabled
|
|
2256
|
+
// Mouse events
|
|
1992
2257
|
if (this.config.enablePan || this.config.enableClickToZoom) {
|
|
1993
2258
|
this.dragSetup = setupMouseEvents(this, this.config, true);
|
|
1994
|
-
this.
|
|
2259
|
+
this.cleanupCallbacks.push(this.dragSetup.cleanup);
|
|
1995
2260
|
}
|
|
1996
|
-
// Keyboard
|
|
2261
|
+
// Keyboard events
|
|
1997
2262
|
withFeatureEnabled(this.config, "enableKeyboard", () => {
|
|
1998
2263
|
const keyboardCleanup = setupKeyboardEvents(this, this.config);
|
|
1999
|
-
this.
|
|
2264
|
+
this.cleanupCallbacks.push(keyboardCleanup);
|
|
2000
2265
|
});
|
|
2001
|
-
// Touch events
|
|
2266
|
+
// Touch events
|
|
2002
2267
|
withFeatureEnabled(this.config, "enableTouch", () => {
|
|
2003
2268
|
const touchCleanup = setupTouchEvents(this);
|
|
2004
|
-
this.
|
|
2269
|
+
this.cleanupCallbacks.push(touchCleanup);
|
|
2005
2270
|
});
|
|
2006
2271
|
// Set up rulers and grid
|
|
2007
2272
|
withFeatureEnabled(this.config, "enableRulers", () => {
|
|
2008
|
-
this.rulers = createRulers(this
|
|
2009
|
-
this.
|
|
2273
|
+
this.rulers = createRulers(this, this.config);
|
|
2274
|
+
this.cleanupCallbacks.push(() => {
|
|
2010
2275
|
if (this.rulers) {
|
|
2011
2276
|
this.rulers.destroy();
|
|
2012
2277
|
}
|
|
@@ -2019,20 +2284,18 @@ class MarkupCanvas {
|
|
|
2019
2284
|
throw error;
|
|
2020
2285
|
}
|
|
2021
2286
|
}
|
|
2022
|
-
// Base canvas properties and methods
|
|
2023
2287
|
get container() {
|
|
2024
|
-
return this.
|
|
2288
|
+
return this.canvas.container;
|
|
2025
2289
|
}
|
|
2026
2290
|
get transformLayer() {
|
|
2027
|
-
return this.
|
|
2291
|
+
return this.canvas.transformLayer;
|
|
2028
2292
|
}
|
|
2029
2293
|
get contentLayer() {
|
|
2030
|
-
return this.
|
|
2294
|
+
return this.canvas.contentLayer;
|
|
2031
2295
|
}
|
|
2032
2296
|
get transform() {
|
|
2033
|
-
return this.
|
|
2297
|
+
return this.canvas.transform;
|
|
2034
2298
|
}
|
|
2035
|
-
// State management getters for React integration
|
|
2036
2299
|
get isReady() {
|
|
2037
2300
|
return this._isReady;
|
|
2038
2301
|
}
|
|
@@ -2040,125 +2303,65 @@ class MarkupCanvas {
|
|
|
2040
2303
|
return this.dragSetup?.isEnabled() || false;
|
|
2041
2304
|
}
|
|
2042
2305
|
get visibleBounds() {
|
|
2043
|
-
return
|
|
2306
|
+
return getVisibleArea(this);
|
|
2044
2307
|
}
|
|
2045
2308
|
getBounds() {
|
|
2046
|
-
return this.
|
|
2309
|
+
return getCanvasBounds(this.canvas, this.config);
|
|
2047
2310
|
}
|
|
2048
2311
|
updateTransform(newTransform) {
|
|
2049
|
-
const result = this.
|
|
2312
|
+
const result = updateTransform(this.canvas, newTransform);
|
|
2050
2313
|
if (result) {
|
|
2051
|
-
this.
|
|
2314
|
+
emitTransformEvents(this.event, this.canvas);
|
|
2052
2315
|
}
|
|
2053
2316
|
return result;
|
|
2054
2317
|
}
|
|
2055
|
-
emitTransformEvents() {
|
|
2056
|
-
const transform = this.baseCanvas.transform;
|
|
2057
|
-
this.listen.emit("transform", transform);
|
|
2058
|
-
this.listen.emit("zoom", transform.scale);
|
|
2059
|
-
this.listen.emit("pan", { x: transform.translateX, y: transform.translateY });
|
|
2060
|
-
}
|
|
2061
2318
|
reset() {
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2319
|
+
const result = resetTransform(this.canvas);
|
|
2320
|
+
if (result) {
|
|
2321
|
+
emitTransformEvents(this.event, this.canvas);
|
|
2322
|
+
}
|
|
2323
|
+
return result;
|
|
2066
2324
|
}
|
|
2067
2325
|
setZoom(zoomLevel) {
|
|
2068
|
-
return
|
|
2069
|
-
return withClampedZoom(this.config, (clamp) => {
|
|
2070
|
-
const newScale = clamp(zoomLevel);
|
|
2071
|
-
const newTransform = {
|
|
2072
|
-
scale: newScale,
|
|
2073
|
-
};
|
|
2074
|
-
return this.updateTransform(newTransform);
|
|
2075
|
-
});
|
|
2076
|
-
});
|
|
2326
|
+
return setZoom(this, this.transformLayer, this.config, this.zoomToPoint.bind(this), zoomLevel);
|
|
2077
2327
|
}
|
|
2078
2328
|
canvasToContent(x, y) {
|
|
2079
|
-
|
|
2329
|
+
const matrix = createMatrix(this.canvas.transform.scale, this.canvas.transform.translateX, this.canvas.transform.translateY);
|
|
2330
|
+
return canvasToContent(x, y, matrix);
|
|
2080
2331
|
}
|
|
2081
2332
|
zoomToPoint(x, y, targetScale) {
|
|
2082
|
-
return
|
|
2083
|
-
const result = this.baseCanvas.zoomToPoint(x, y, targetScale);
|
|
2084
|
-
if (result) {
|
|
2085
|
-
this.emitTransformEvents();
|
|
2086
|
-
}
|
|
2087
|
-
return result;
|
|
2088
|
-
});
|
|
2333
|
+
return zoomToPoint(this.canvas, this.transformLayer, this.config, x, y, targetScale);
|
|
2089
2334
|
}
|
|
2090
2335
|
resetView() {
|
|
2091
|
-
return
|
|
2092
|
-
const result = this.baseCanvas.resetView ? this.baseCanvas.resetView() : false;
|
|
2093
|
-
if (result) {
|
|
2094
|
-
this.emitTransformEvents();
|
|
2095
|
-
}
|
|
2096
|
-
return result;
|
|
2097
|
-
});
|
|
2336
|
+
return resetView(this.canvas, this.transformLayer, this.config);
|
|
2098
2337
|
}
|
|
2099
|
-
|
|
2100
|
-
return
|
|
2101
|
-
const result = this.baseCanvas.zoomToFitContent();
|
|
2102
|
-
if (result) {
|
|
2103
|
-
this.emitTransformEvents();
|
|
2104
|
-
}
|
|
2105
|
-
return result;
|
|
2106
|
-
});
|
|
2338
|
+
resetViewToCenter() {
|
|
2339
|
+
return resetViewToCenter(this, this.transformLayer, this.config, this.zoomToPoint.bind(this));
|
|
2107
2340
|
}
|
|
2108
|
-
// Pan methods
|
|
2109
2341
|
panLeft(distance) {
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
translateX: this.baseCanvas.transform.translateX + panDistance,
|
|
2113
|
-
};
|
|
2114
|
-
return this.updateTransform(newTransform);
|
|
2342
|
+
return (panLeft(this.canvas, this.config, this.updateTransform.bind(this)) ||
|
|
2343
|
+
(distance ? panLeft(this.canvas, { ...this.config, keyboardPanStep: distance }, this.updateTransform.bind(this)) : false));
|
|
2115
2344
|
}
|
|
2116
2345
|
panRight(distance) {
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
translateX: this.baseCanvas.transform.translateX - panDistance,
|
|
2120
|
-
};
|
|
2121
|
-
return this.updateTransform(newTransform);
|
|
2346
|
+
return (panRight(this.canvas, this.config, this.updateTransform.bind(this)) ||
|
|
2347
|
+
(distance ? panRight(this.canvas, { ...this.config, keyboardPanStep: distance }, this.updateTransform.bind(this)) : false));
|
|
2122
2348
|
}
|
|
2123
2349
|
panUp(distance) {
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
translateY: this.baseCanvas.transform.translateY + panDistance,
|
|
2127
|
-
};
|
|
2128
|
-
return this.updateTransform(newTransform);
|
|
2350
|
+
return (panUp(this.canvas, this.config, this.updateTransform.bind(this)) ||
|
|
2351
|
+
(distance ? panUp(this.canvas, { ...this.config, keyboardPanStep: distance }, this.updateTransform.bind(this)) : false));
|
|
2129
2352
|
}
|
|
2130
2353
|
panDown(distance) {
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
translateY: this.baseCanvas.transform.translateY - panDistance,
|
|
2134
|
-
};
|
|
2135
|
-
return this.updateTransform(newTransform);
|
|
2354
|
+
return (panDown(this.canvas, this.config, this.updateTransform.bind(this)) ||
|
|
2355
|
+
(distance ? panDown(this.canvas, { ...this.config, keyboardPanStep: distance }, this.updateTransform.bind(this)) : false));
|
|
2136
2356
|
}
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
return withTransition(this.transformLayer, this.config, () => {
|
|
2140
|
-
return withClampedZoom(this.config, (clamp) => {
|
|
2141
|
-
const newScale = clamp(this.baseCanvas.transform.scale * (1 + factor));
|
|
2142
|
-
const newTransform = {
|
|
2143
|
-
scale: newScale,
|
|
2144
|
-
};
|
|
2145
|
-
return this.updateTransform(newTransform);
|
|
2146
|
-
});
|
|
2147
|
-
});
|
|
2357
|
+
zoomIn(factor = 0.5) {
|
|
2358
|
+
return zoomIn(this, this.transformLayer, this.config, this.zoomToPoint.bind(this), factor);
|
|
2148
2359
|
}
|
|
2149
|
-
zoomOut(factor = 0.
|
|
2150
|
-
return
|
|
2151
|
-
return withClampedZoom(this.config, (clamp) => {
|
|
2152
|
-
const newScale = clamp(this.baseCanvas.transform.scale * (1 - factor));
|
|
2153
|
-
const newTransform = {
|
|
2154
|
-
scale: newScale,
|
|
2155
|
-
};
|
|
2156
|
-
return this.updateTransform(newTransform);
|
|
2157
|
-
});
|
|
2158
|
-
});
|
|
2360
|
+
zoomOut(factor = 0.5) {
|
|
2361
|
+
return zoomOut(this, this.transformLayer, this.config, this.zoomToPoint.bind(this), factor);
|
|
2159
2362
|
}
|
|
2160
2363
|
resetZoom() {
|
|
2161
|
-
return this.
|
|
2364
|
+
return this.resetViewToCenter();
|
|
2162
2365
|
}
|
|
2163
2366
|
// Mouse drag control methods
|
|
2164
2367
|
enableMouseDrag() {
|
|
@@ -2170,110 +2373,68 @@ class MarkupCanvas {
|
|
|
2170
2373
|
isMouseDragEnabled() {
|
|
2171
2374
|
return this.dragSetup?.isEnabled() ?? false;
|
|
2172
2375
|
}
|
|
2173
|
-
// Grid control methods
|
|
2174
2376
|
toggleGrid() {
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2377
|
+
const result = toggleGrid(this.rulers);
|
|
2378
|
+
if (result) {
|
|
2379
|
+
this.event.emit("gridVisibility", this.isGridVisible());
|
|
2178
2380
|
}
|
|
2179
|
-
return
|
|
2381
|
+
return result;
|
|
2180
2382
|
}
|
|
2181
2383
|
showGrid() {
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2384
|
+
const result = showGrid(this.rulers);
|
|
2385
|
+
if (result) {
|
|
2386
|
+
this.event.emit("gridVisibility", true);
|
|
2185
2387
|
}
|
|
2186
|
-
return
|
|
2388
|
+
return result;
|
|
2187
2389
|
}
|
|
2188
2390
|
hideGrid() {
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2391
|
+
const result = hideGrid(this.rulers);
|
|
2392
|
+
if (result) {
|
|
2393
|
+
this.event.emit("gridVisibility", false);
|
|
2192
2394
|
}
|
|
2193
|
-
return
|
|
2395
|
+
return result;
|
|
2194
2396
|
}
|
|
2195
2397
|
isGridVisible() {
|
|
2196
|
-
|
|
2197
|
-
return this.rulers.gridOverlay.style.display !== "none";
|
|
2198
|
-
}
|
|
2199
|
-
return false;
|
|
2398
|
+
return isGridVisible(this.rulers);
|
|
2200
2399
|
}
|
|
2201
|
-
// Ruler control methods
|
|
2202
2400
|
toggleRulers() {
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
this.rulers.hide();
|
|
2207
|
-
}
|
|
2208
|
-
else {
|
|
2209
|
-
this.rulers.show();
|
|
2210
|
-
}
|
|
2211
|
-
return true;
|
|
2401
|
+
const result = toggleRulers(this.rulers, () => this.areRulersVisible());
|
|
2402
|
+
if (result) {
|
|
2403
|
+
this.event.emit("rulersVisibility", this.areRulersVisible());
|
|
2212
2404
|
}
|
|
2213
|
-
return
|
|
2405
|
+
return result;
|
|
2214
2406
|
}
|
|
2215
2407
|
showRulers() {
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2408
|
+
const result = showRulers(this.rulers);
|
|
2409
|
+
if (result) {
|
|
2410
|
+
this.event.emit("rulersVisibility", true);
|
|
2219
2411
|
}
|
|
2220
|
-
return
|
|
2412
|
+
return result;
|
|
2221
2413
|
}
|
|
2222
2414
|
hideRulers() {
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2415
|
+
const result = hideRulers(this.rulers);
|
|
2416
|
+
if (result) {
|
|
2417
|
+
this.event.emit("rulersVisibility", false);
|
|
2226
2418
|
}
|
|
2227
|
-
return
|
|
2419
|
+
return result;
|
|
2228
2420
|
}
|
|
2229
2421
|
areRulersVisible() {
|
|
2230
|
-
|
|
2231
|
-
return this.rulers.horizontalRuler.style.display !== "none";
|
|
2232
|
-
}
|
|
2233
|
-
return false;
|
|
2422
|
+
return areRulersVisible(this.rulers);
|
|
2234
2423
|
}
|
|
2235
|
-
// Utility methods
|
|
2236
2424
|
centerContent() {
|
|
2237
|
-
return
|
|
2238
|
-
const bounds = this.baseCanvas.getBounds();
|
|
2239
|
-
const centerX = (bounds.width - bounds.contentWidth * this.baseCanvas.transform.scale) / 2;
|
|
2240
|
-
const centerY = (bounds.height - bounds.contentHeight * this.baseCanvas.transform.scale) / 2;
|
|
2241
|
-
return this.updateTransform({
|
|
2242
|
-
translateX: centerX,
|
|
2243
|
-
translateY: centerY,
|
|
2244
|
-
});
|
|
2245
|
-
});
|
|
2425
|
+
return centerContent(this.canvas, this.config, this.updateTransform.bind(this), this.transformLayer);
|
|
2246
2426
|
}
|
|
2247
2427
|
fitToScreen() {
|
|
2248
|
-
return
|
|
2249
|
-
const result = this.baseCanvas.zoomToFitContent();
|
|
2250
|
-
if (result) {
|
|
2251
|
-
this.emitTransformEvents();
|
|
2252
|
-
}
|
|
2253
|
-
return result;
|
|
2254
|
-
});
|
|
2428
|
+
return fitToScreen(this.canvas, this.transformLayer, this.config);
|
|
2255
2429
|
}
|
|
2256
2430
|
getVisibleArea() {
|
|
2257
|
-
|
|
2258
|
-
return bounds.visibleArea;
|
|
2431
|
+
return getVisibleArea(this);
|
|
2259
2432
|
}
|
|
2260
2433
|
isPointVisible(x, y) {
|
|
2261
|
-
|
|
2262
|
-
return x >= visibleArea.x && x <= visibleArea.x + visibleArea.width && y >= visibleArea.y && y <= visibleArea.y + visibleArea.height;
|
|
2434
|
+
return isPointVisible(this, x, y);
|
|
2263
2435
|
}
|
|
2264
2436
|
scrollToPoint(x, y) {
|
|
2265
|
-
return
|
|
2266
|
-
const bounds = this.baseCanvas.getBounds();
|
|
2267
|
-
const centerX = bounds.width / 2;
|
|
2268
|
-
const centerY = bounds.height / 2;
|
|
2269
|
-
// Calculate new translation to center the point
|
|
2270
|
-
const newTranslateX = centerX - x * this.baseCanvas.transform.scale;
|
|
2271
|
-
const newTranslateY = centerY - y * this.baseCanvas.transform.scale;
|
|
2272
|
-
return this.updateTransform({
|
|
2273
|
-
translateX: newTranslateX,
|
|
2274
|
-
translateY: newTranslateY,
|
|
2275
|
-
});
|
|
2276
|
-
});
|
|
2437
|
+
return scrollToPoint(this.canvas, this.config, x, y, this.updateTransform.bind(this), this.transformLayer);
|
|
2277
2438
|
}
|
|
2278
2439
|
// Configuration access
|
|
2279
2440
|
getConfig() {
|
|
@@ -2284,28 +2445,28 @@ class MarkupCanvas {
|
|
|
2284
2445
|
}
|
|
2285
2446
|
// Theme management
|
|
2286
2447
|
updateThemeMode(mode) {
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
this.config
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
}
|
|
2448
|
+
this.config = createMarkupCanvasConfig({ ...this.config, themeMode: mode });
|
|
2449
|
+
updateThemeMode(this.canvas.container, this.config, this.rulers, mode);
|
|
2450
|
+
}
|
|
2451
|
+
toggleThemeMode() {
|
|
2452
|
+
const currentMode = this.config.themeMode;
|
|
2453
|
+
const newMode = currentMode === "light" ? "dark" : "light";
|
|
2454
|
+
this.updateThemeMode(newMode);
|
|
2455
|
+
return newMode;
|
|
2456
|
+
}
|
|
2457
|
+
// Transition management
|
|
2458
|
+
updateTransition(enabled) {
|
|
2459
|
+
this.config = createMarkupCanvasConfig({ ...this.config, enableTransition: enabled });
|
|
2460
|
+
}
|
|
2461
|
+
toggleTransitionMode() {
|
|
2462
|
+
const newEnableTransition = toggleTransition(this.config.enableTransition);
|
|
2463
|
+
this.updateTransition(newEnableTransition);
|
|
2464
|
+
return newEnableTransition;
|
|
2299
2465
|
}
|
|
2300
2466
|
// Cleanup method
|
|
2301
2467
|
cleanup() {
|
|
2302
|
-
this.
|
|
2303
|
-
|
|
2304
|
-
if (this.postMessageCleanup) {
|
|
2305
|
-
this.postMessageCleanup();
|
|
2306
|
-
this.postMessageCleanup = null;
|
|
2307
|
-
}
|
|
2308
|
-
this.cleanupFunctions.forEach((cleanup) => {
|
|
2468
|
+
cleanupWindowBinding(this.config);
|
|
2469
|
+
this.cleanupCallbacks.forEach((cleanup) => {
|
|
2309
2470
|
try {
|
|
2310
2471
|
cleanup();
|
|
2311
2472
|
}
|
|
@@ -2313,22 +2474,22 @@ class MarkupCanvas {
|
|
|
2313
2474
|
console.warn("Error during cleanup:", cleanupError);
|
|
2314
2475
|
}
|
|
2315
2476
|
});
|
|
2316
|
-
this.
|
|
2477
|
+
this.cleanupCallbacks = [];
|
|
2317
2478
|
// Remove all event listeners
|
|
2318
2479
|
this.removeAllListeners();
|
|
2319
2480
|
}
|
|
2320
2481
|
// Event emitter delegation methods
|
|
2321
2482
|
on(event, handler) {
|
|
2322
|
-
this.
|
|
2483
|
+
this.event.on(event, handler);
|
|
2323
2484
|
}
|
|
2324
2485
|
off(event, handler) {
|
|
2325
|
-
this.
|
|
2486
|
+
this.event.off(event, handler);
|
|
2326
2487
|
}
|
|
2327
2488
|
emit(event, data) {
|
|
2328
|
-
this.
|
|
2489
|
+
this.event.emit(event, data);
|
|
2329
2490
|
}
|
|
2330
2491
|
removeAllListeners() {
|
|
2331
|
-
this.
|
|
2492
|
+
this.event.removeAllListeners();
|
|
2332
2493
|
}
|
|
2333
2494
|
destroy() {
|
|
2334
2495
|
this.cleanup();
|