@preference-sl/pref-viewer 2.10.0 → 2.11.0-beta.1
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/package.json +6 -3
- package/src/babylonjs-controller.js +929 -0
- package/src/file-storage.js +288 -0
- package/src/gltf-resolver.js +288 -0
- package/src/index.js +492 -962
- package/src/panzoom-controller.js +494 -0
- package/src/pref-viewer-2d.js +441 -0
- package/src/pref-viewer-3d-data.js +178 -0
- package/src/pref-viewer-3d.js +457 -0
- package/src/pref-viewer-task.js +54 -0
- package/src/svg-resolver.js +281 -0
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
import "@panzoom/panzoom";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PanzoomController - Encapsulates the logic for managing pan and zoom interactions on a given DOM element.
|
|
5
|
+
*
|
|
6
|
+
* Responsibilities:
|
|
7
|
+
* - Provides an interface to enable, disable, and control pan/zoom interactions.
|
|
8
|
+
* - Manages event listeners for mouse, keyboard, and touch interactions.
|
|
9
|
+
* - Tracks the current pan/zoom state and invokes a callback when the state changes.
|
|
10
|
+
* - Supports zooming in/out, panning, resetting, and mouse wheel zoom.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* - Instantiate the controller with a DOM element and optional configuration:
|
|
14
|
+
* const controller = new PanzoomController(wrapperElement, options, stateChangeCallback);
|
|
15
|
+
* - Use public methods like `enable()`, `zoomIn()`, `pan(x, y)`, etc., to control interactions.
|
|
16
|
+
* - Call `disable()` to remove all event listeners and destroy the Panzoom instance.
|
|
17
|
+
*
|
|
18
|
+
* Constructor Parameters:
|
|
19
|
+
* - `wrapper` (HTMLElement): The DOM element to apply pan/zoom interactions to.
|
|
20
|
+
* - `options` (object): Configuration options for Panzoom (e.g., minScale, maxScale, step).
|
|
21
|
+
* - `changedCallback` (function): Optional callback invoked when the pan/zoom state changes.
|
|
22
|
+
*
|
|
23
|
+
* Public Methods:
|
|
24
|
+
* - `enable()`: Enables the Panzoom instance and initializes it if not already enabled.
|
|
25
|
+
* - `disable()`: Disables the Panzoom instance and removes all event listeners.
|
|
26
|
+
* - `enableEvents()`: Attaches all required event listeners for interactions.
|
|
27
|
+
* - `disableEvents()`: Removes all previously attached event listeners.
|
|
28
|
+
* - `pan(x, y)`: Pans the view to the specified coordinates.
|
|
29
|
+
* - `reset()`: Resets pan and zoom to fit the entire content within the available space.
|
|
30
|
+
* - `zoomIn(focal?)`: Zooms in by one step, optionally centered on a focal point.
|
|
31
|
+
* - `zoomOut(focal?)`: Zooms out by one step, optionally centered on a focal point.
|
|
32
|
+
*
|
|
33
|
+
* Getters:
|
|
34
|
+
* - `panzoom`: Returns the current Panzoom instance or `null` if not initialized.
|
|
35
|
+
* - `state`: Returns the current pan/zoom state (e.g., moved, scaled, maximized, minimized).
|
|
36
|
+
*
|
|
37
|
+
* Private Methods:
|
|
38
|
+
* - `#checkPanzoomState(transform)`: Updates the internal state and invokes the state change callback.
|
|
39
|
+
* - `#resetTransform()`: Resets the transform applied to the wrapper element.
|
|
40
|
+
* - `#setFocus()`: Sets focus on the parent element to enable keyboard interactions.
|
|
41
|
+
* - `#onPanzoomStart(e)`: Handles the start of a pan/zoom interaction.
|
|
42
|
+
* - `#onPanzoomChange(e)`: Handles changes in pan/zoom state.
|
|
43
|
+
* - `#onPanzoomEnd(e)`: Handles the end of a pan/zoom interaction.
|
|
44
|
+
* - `#onZoomWithWheel(e)`: Handles zoom interactions via the mouse wheel.
|
|
45
|
+
* - `#enableMouseWheelZoom()`: Enables zooming with the mouse wheel.
|
|
46
|
+
* - `#disableMouseWheelZoom()`: Disables zooming with the mouse wheel.
|
|
47
|
+
* - `#getDistanceBetweenPoints(point1, point2)`: Calculates the Euclidean distance between two points.
|
|
48
|
+
* - `#getPointFromEvent(e)`: Extracts client coordinates from a mouse or touch event.
|
|
49
|
+
*
|
|
50
|
+
* Notes:
|
|
51
|
+
* - Designed to work with the Panzoom library for managing pan/zoom interactions.
|
|
52
|
+
* - Provides a clean separation of concerns by encapsulating all pan/zoom logic in a single class.
|
|
53
|
+
* - Can be extended or customized by overriding methods or providing additional options.
|
|
54
|
+
*/
|
|
55
|
+
export default class PanzoomController {
|
|
56
|
+
#changedCallback = null;
|
|
57
|
+
#interactionOptions = {
|
|
58
|
+
clickThreshold: 6, // Threshold to avoid false clicks on elements when panning or zooming
|
|
59
|
+
};
|
|
60
|
+
#options = {
|
|
61
|
+
canvas: true,
|
|
62
|
+
minScale: 0.1,
|
|
63
|
+
maxScale: 10,
|
|
64
|
+
step: 0.3,
|
|
65
|
+
cursor: "default",
|
|
66
|
+
disablePan: false,
|
|
67
|
+
disableZoom: false,
|
|
68
|
+
};
|
|
69
|
+
#panzoom = null; // Panzoom Object
|
|
70
|
+
#pointerEvents = {
|
|
71
|
+
lastPointerDownPosition: null,
|
|
72
|
+
partialCounter: 0,
|
|
73
|
+
totalCounter: 0,
|
|
74
|
+
};
|
|
75
|
+
#state = {
|
|
76
|
+
moved: false,
|
|
77
|
+
scaled: false,
|
|
78
|
+
maximized: false,
|
|
79
|
+
minimized: false,
|
|
80
|
+
};
|
|
81
|
+
#wrapper = null;
|
|
82
|
+
|
|
83
|
+
constructor(wrapper = null, options = {}, changedCallback = null) {
|
|
84
|
+
this.#wrapper = wrapper;
|
|
85
|
+
Object.assign(this.#options, options);
|
|
86
|
+
this.#changedCallback = changedCallback;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Calculate Euclidean distance between two points {x,y}.
|
|
91
|
+
* @private
|
|
92
|
+
* @param {{x:number,y:number}} point1
|
|
93
|
+
* @param {{x:number,y:number}} point2
|
|
94
|
+
* @returns {number} Distance in pixels (0 when points are invalid).
|
|
95
|
+
*/
|
|
96
|
+
#getDistanceBetweenPoints(point1, point2) {
|
|
97
|
+
let distance = 0;
|
|
98
|
+
if (point1 && point2) {
|
|
99
|
+
distance = Math.sqrt(Math.pow(point2.x - point1.x, 2) + Math.pow(point2.y - point1.y, 2));
|
|
100
|
+
}
|
|
101
|
+
return distance;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Extract client coordinates from a mouse/touch event.
|
|
106
|
+
* @private
|
|
107
|
+
* @param {Event} e - Mouse or touch event.
|
|
108
|
+
* @returns {{x:number,y:number}|null} Point or null if coordinates not present.
|
|
109
|
+
*/
|
|
110
|
+
#getPointFromEvent(e) {
|
|
111
|
+
if (e.clientX && e.clientY) {
|
|
112
|
+
return {
|
|
113
|
+
x: e.clientX,
|
|
114
|
+
y: e.clientY,
|
|
115
|
+
};
|
|
116
|
+
} else {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Update internal pan/zoom state and emit a custom event with current values.
|
|
123
|
+
* If a changed callback is defined, it is invoked with the updated state object.
|
|
124
|
+
* @private
|
|
125
|
+
* @param {{scale:number,x:number,y:number}} transform - Current transform values.
|
|
126
|
+
* @returns {void}
|
|
127
|
+
*/
|
|
128
|
+
#checkPanzoomState(transform) {
|
|
129
|
+
this.#state = {
|
|
130
|
+
moved: transform.x !== 0 || transform.y !== 0,
|
|
131
|
+
scaled: transform.scale !== 1,
|
|
132
|
+
maximized: transform.scale === this.#options.maxScale,
|
|
133
|
+
minimized: transform.scale === this.#options.minScale,
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
if (this.#changedCallback && typeof this.#changedCallback === "function") {
|
|
137
|
+
this.#changedCallback(this.#state);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Remove any transform applied to the wrapper (reset pan/zoom). Resets internal Panzoom state accordingly.
|
|
143
|
+
* @private
|
|
144
|
+
* @returns {void}
|
|
145
|
+
*/
|
|
146
|
+
#resetTransform() {
|
|
147
|
+
const transform = {
|
|
148
|
+
scale: 1,
|
|
149
|
+
x: 0,
|
|
150
|
+
y: 0,
|
|
151
|
+
};
|
|
152
|
+
if (this.#wrapper) {
|
|
153
|
+
this.#wrapper.style.removeProperty("transform");
|
|
154
|
+
}
|
|
155
|
+
this.#checkPanzoomState(transform);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Set focus on the viewer's parent element to enable keyboard interactions.
|
|
160
|
+
* @private
|
|
161
|
+
* @returns {void}
|
|
162
|
+
* @description Focus is set on the parent element because when Panzoom had focus with a positive Y translation (part of the drawing outside the parent container), the Y translation was reset.
|
|
163
|
+
*/
|
|
164
|
+
#setFocus() {
|
|
165
|
+
if (this.#wrapper) {
|
|
166
|
+
this.#wrapper.parentElement.focus();
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Contextmenu handler to prevent the browser's default context menu.
|
|
172
|
+
* @private
|
|
173
|
+
* @param {Event} e - Contextmenu event.
|
|
174
|
+
* @returns {void}
|
|
175
|
+
*/
|
|
176
|
+
#onContextMenu(e) {
|
|
177
|
+
e.preventDefault();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Keyboard handler to support '+' and '-' shortcuts for zoom.
|
|
182
|
+
* @private
|
|
183
|
+
* @param {KeyboardEvent} e - Key event.
|
|
184
|
+
* @returns {void}
|
|
185
|
+
*/
|
|
186
|
+
#onKeyUp(e) {
|
|
187
|
+
// '+' zoom in
|
|
188
|
+
if (e.key === "+") {
|
|
189
|
+
this.zoomIn();
|
|
190
|
+
}
|
|
191
|
+
// '-' zoom out
|
|
192
|
+
if (e.key === "-") {
|
|
193
|
+
this.zoomOut();
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Panzoom "change" (pan, zoom, reset) event handler. Updates internal transform state.
|
|
199
|
+
* @private
|
|
200
|
+
* @param {CustomEvent} e - Panzoom custom event with detail.scale/x/y
|
|
201
|
+
* @returns {void}
|
|
202
|
+
* @description This event is not fired when options.setTransform is called directly.
|
|
203
|
+
*/
|
|
204
|
+
#onPanzoomChange(e) {
|
|
205
|
+
const transform = {
|
|
206
|
+
scale: e.detail.scale,
|
|
207
|
+
x: e.detail.x,
|
|
208
|
+
y: e.detail.y,
|
|
209
|
+
};
|
|
210
|
+
this.#checkPanzoomState(transform);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Panzoom "end" event handler. Determines whether the gesture should be considered a click (for selection) or a pan/zoom gesture and acts accordingly.
|
|
215
|
+
* @private
|
|
216
|
+
* @param {CustomEvent} e - Panzoom custom event with originalEvent property.
|
|
217
|
+
* @returns {void}
|
|
218
|
+
* @todo Implement selection/click logic.
|
|
219
|
+
*/
|
|
220
|
+
#onPanzoomEnd(e) {
|
|
221
|
+
this.#pointerEvents.partialCounter--;
|
|
222
|
+
|
|
223
|
+
if (this.#pointerEvents.partialCounter > 0) {
|
|
224
|
+
return;
|
|
225
|
+
} else if (this.#pointerEvents.totalCounter > 1) {
|
|
226
|
+
this.#pointerEvents.partialCounter = 0;
|
|
227
|
+
this.#pointerEvents.totalCounter = 0;
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
this.#pointerEvents.partialCounter = 0;
|
|
232
|
+
this.#pointerEvents.totalCounter = 0;
|
|
233
|
+
|
|
234
|
+
const originalEvent = e.detail.originalEvent;
|
|
235
|
+
const point = this.#getPointFromEvent(originalEvent);
|
|
236
|
+
const distance = this.#getDistanceBetweenPoints(point, this.#pointerEvents.lastPointerDownPosition);
|
|
237
|
+
|
|
238
|
+
let proceedToPick = true;
|
|
239
|
+
|
|
240
|
+
if (!point || distance > this.#interactionOptions.clickThreshold) {
|
|
241
|
+
proceedToPick = false;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (originalEvent.button !== 0) {
|
|
245
|
+
proceedToPick = false;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
this.#pointerEvents.lastPointerDownPosition = null;
|
|
249
|
+
|
|
250
|
+
if (!proceedToPick) {
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (!originalEvent.target) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Selection/click logic can be implemented here.
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Panzoom "start" event handler. Store pointer state and set focus.
|
|
263
|
+
* @private
|
|
264
|
+
* @param {CustomEvent} e - Panzoom custom event with originalEvent property.
|
|
265
|
+
* @returns {void}
|
|
266
|
+
*/
|
|
267
|
+
#onPanzoomStart(e) {
|
|
268
|
+
const originalEvent = e.detail.originalEvent;
|
|
269
|
+
this.#pointerEvents.partialCounter++;
|
|
270
|
+
this.#pointerEvents.totalCounter++;
|
|
271
|
+
this.#pointerEvents.lastPointerDownPosition = this.#getPointFromEvent(originalEvent);
|
|
272
|
+
this.#setFocus();
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Delegate wheel events to Panzoom zoom handler.
|
|
277
|
+
* @private
|
|
278
|
+
* @param {WheelEvent} e - Wheel event.
|
|
279
|
+
* @returns {void}
|
|
280
|
+
*/
|
|
281
|
+
#onZoomWithWheel(e) {
|
|
282
|
+
if (!this.#panzoom) {
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
this.#panzoom.zoomWithWheel(e);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Disable mouse wheel zoom by removing the wheel event listener from the parent element.
|
|
290
|
+
* @private
|
|
291
|
+
* @returns {void}
|
|
292
|
+
*/
|
|
293
|
+
#disableMouseWheelZoom() {
|
|
294
|
+
if (!this.#panzoom) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
this.#wrapper.parentElement.removeEventListener("wheel", this.#onZoomWithWheel.bind(this));
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Enable mouse wheel zoom by adding the wheel event listener to the parent element.
|
|
302
|
+
* @private
|
|
303
|
+
* @returns {void}
|
|
304
|
+
* @description
|
|
305
|
+
* Removes any previous wheel event listener before adding a new one to avoid duplicates.
|
|
306
|
+
*/
|
|
307
|
+
#enableMouseWheelZoom() {
|
|
308
|
+
if (!this.#panzoom) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
this.#disableMouseWheelZoom();
|
|
312
|
+
this.#wrapper.parentElement.addEventListener("wheel", this.#onZoomWithWheel.bind(this));
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* ---------------------------
|
|
317
|
+
* Public methods
|
|
318
|
+
* ---------------------------
|
|
319
|
+
*/
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Enables the Panzoom instance for the wrapper element.
|
|
323
|
+
* Initializes Panzoom with the provided options if not already enabled.
|
|
324
|
+
* @public
|
|
325
|
+
* @returns {void}
|
|
326
|
+
*/
|
|
327
|
+
enable() {
|
|
328
|
+
if (!this.#wrapper) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
if (!this.#panzoom) {
|
|
332
|
+
this.#panzoom = Panzoom(this.#wrapper, this.#options);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Disables the Panzoom instance and removes all related event listeners.
|
|
338
|
+
* Destroys the Panzoom object and resets transforms.
|
|
339
|
+
* @public
|
|
340
|
+
* @returns {void}
|
|
341
|
+
*/
|
|
342
|
+
disable() {
|
|
343
|
+
if (!this.#panzoom) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
this.disableEvents();
|
|
347
|
+
this.#panzoom.destroy();
|
|
348
|
+
this.#panzoom = null;
|
|
349
|
+
this.#resetTransform();
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Subscribes all required Panzoom and interaction event listeners.
|
|
354
|
+
* Adds listeners for panzoom events, keyboard shortcuts, mouse wheel zoom, and context menu.
|
|
355
|
+
* Sets focus and enables keyboard navigation.
|
|
356
|
+
* @public
|
|
357
|
+
* @returns {void}
|
|
358
|
+
*/
|
|
359
|
+
enableEvents() {
|
|
360
|
+
if (!this.#panzoom) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
this.disableEvents();
|
|
365
|
+
|
|
366
|
+
this.#wrapper.addEventListener("panzoomstart", this.#onPanzoomStart.bind(this));
|
|
367
|
+
this.#wrapper.addEventListener("panzoomchange", this.#onPanzoomChange.bind(this));
|
|
368
|
+
this.#wrapper.addEventListener("panzoomend", this.#onPanzoomEnd.bind(this));
|
|
369
|
+
this.#wrapper.parentElement.addEventListener("keyup", this.#onKeyUp.bind(this));
|
|
370
|
+
this.#wrapper.parentElement.addEventListener("focus", this.#enableMouseWheelZoom.bind(this), true);
|
|
371
|
+
this.#wrapper.parentElement.addEventListener("blur", this.#disableMouseWheelZoom.bind(this), true);
|
|
372
|
+
this.#wrapper.parentElement.addEventListener("contextmenu", this.#onContextMenu);
|
|
373
|
+
this.#wrapper.parentElement.setAttribute("tabindex", 0);
|
|
374
|
+
this.#setFocus();
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Unsubscribes all Panzoom and interaction event listeners previously attached.
|
|
379
|
+
* Removes listeners for panzoom events, keyboard shortcuts, mouse wheel zoom, and context menu.
|
|
380
|
+
* @public
|
|
381
|
+
* @returns {void}
|
|
382
|
+
*/
|
|
383
|
+
disableEvents() {
|
|
384
|
+
if (!this.#wrapper) {
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
this.#wrapper.parentElement.removeAttribute("tabindex");
|
|
388
|
+
this.#wrapper.removeEventListener("panzoomstart", this.#onPanzoomStart.bind(this));
|
|
389
|
+
this.#wrapper.removeEventListener("panzoomchange", this.#onPanzoomChange.bind(this));
|
|
390
|
+
this.#wrapper.removeEventListener("panzoomend", this.#onPanzoomEnd.bind(this));
|
|
391
|
+
this.#wrapper.parentElement.removeEventListener("keyup", this.#onKeyUp.bind(this));
|
|
392
|
+
this.#wrapper.parentElement.removeEventListener("focus", this.#enableMouseWheelZoom.bind(this));
|
|
393
|
+
this.#wrapper.parentElement.removeEventListener("blur", this.#disableMouseWheelZoom.bind(this));
|
|
394
|
+
this.#wrapper.parentElement.removeEventListener("contextmenu", this.#onContextMenu);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Pans the SVG view to the specified coordinates.
|
|
399
|
+
* Sets focus on the parent element after panning.
|
|
400
|
+
* @public
|
|
401
|
+
* @param {number} x - The x coordinate to pan to.
|
|
402
|
+
* @param {number} y - The y coordinate to pan to.
|
|
403
|
+
* @returns {void}
|
|
404
|
+
*/
|
|
405
|
+
pan(x, y) {
|
|
406
|
+
if (!this.#panzoom) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
if (typeof x !== "number" || typeof y !== "number") {
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
this.#panzoom.pan(x, y, { animate: false });
|
|
413
|
+
this.#setFocus();
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Resets pan and zoom so the entire SVG drawing fits within the available space.
|
|
418
|
+
* Sets focus on the parent element after resetting.
|
|
419
|
+
* @public
|
|
420
|
+
* @returns {void}
|
|
421
|
+
*/
|
|
422
|
+
reset() {
|
|
423
|
+
if (!this.#panzoom) {
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
this.#panzoom.reset({ animate: false });
|
|
427
|
+
this.#setFocus();
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Zooms in the SVG view by one step.
|
|
432
|
+
* If a focal point is provided, the zoom is centered on that point; otherwise, it is centered on the drawing.
|
|
433
|
+
* Sets focus on the parent element after zooming.
|
|
434
|
+
* @param {{x:number, y:number}=} focal - Optional focal point for the zoom operation.
|
|
435
|
+
* @public
|
|
436
|
+
* @returns {void}
|
|
437
|
+
*/
|
|
438
|
+
zoomIn(focal) {
|
|
439
|
+
if (!this.#panzoom) {
|
|
440
|
+
return;
|
|
441
|
+
}
|
|
442
|
+
const options = {
|
|
443
|
+
exponential: false,
|
|
444
|
+
animate: false,
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
if (typeof focal === "object" && focal && "x" in focal && "y" in focal) {
|
|
448
|
+
options.focal = focal;
|
|
449
|
+
}
|
|
450
|
+
this.#panzoom.zoomIn(options);
|
|
451
|
+
this.#setFocus();
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Zooms out the SVG view by one step.
|
|
456
|
+
* If a focal point is provided, the zoom is centered on that point; otherwise, it is centered on the drawing.
|
|
457
|
+
* Sets focus on the parent element after zooming.
|
|
458
|
+
* @param {{x:number, y:number}=} focal - Optional focal point for the zoom operation.
|
|
459
|
+
* @public
|
|
460
|
+
* @returns {void}
|
|
461
|
+
*/
|
|
462
|
+
zoomOut(focal) {
|
|
463
|
+
if (!this.#panzoom) {
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
const options = {
|
|
467
|
+
exponential: false,
|
|
468
|
+
animate: false,
|
|
469
|
+
};
|
|
470
|
+
if (typeof focal === "object" && focal && "x" in focal && "y" in focal) {
|
|
471
|
+
options.focal = focal;
|
|
472
|
+
}
|
|
473
|
+
this.#panzoom.zoomOut(options);
|
|
474
|
+
this.#setFocus();
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* Returns the current Panzoom instance.
|
|
479
|
+
* @public
|
|
480
|
+
* @returns {object|null} The Panzoom object or null if not initialized.
|
|
481
|
+
*/
|
|
482
|
+
get panzoom() {
|
|
483
|
+
return this.#panzoom;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Returns the current pan/zoom state.
|
|
488
|
+
* @public
|
|
489
|
+
* @returns {object} The state object: { moved, scaled, maximized, minimized }.
|
|
490
|
+
*/
|
|
491
|
+
get state() {
|
|
492
|
+
return this.#state;
|
|
493
|
+
}
|
|
494
|
+
}
|