js-draw 0.1.7 → 0.1.10
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/CHANGELOG.md +15 -0
- package/README.md +15 -3
- package/dist/bundle.js +1 -1
- package/dist/src/Editor.d.ts +1 -0
- package/dist/src/Editor.js +32 -15
- package/dist/src/UndoRedoHistory.js +3 -0
- package/dist/src/bundle/bundled.d.ts +2 -1
- package/dist/src/bundle/bundled.js +2 -1
- package/dist/src/components/builders/RectangleBuilder.d.ts +3 -1
- package/dist/src/components/builders/RectangleBuilder.js +17 -8
- package/dist/src/geometry/LineSegment2.d.ts +1 -0
- package/dist/src/geometry/LineSegment2.js +16 -0
- package/dist/src/geometry/Rect2.d.ts +1 -0
- package/dist/src/geometry/Rect2.js +16 -0
- package/dist/src/localizations/en.d.ts +3 -0
- package/dist/src/localizations/en.js +4 -0
- package/dist/src/localizations/es.d.ts +3 -0
- package/dist/src/localizations/es.js +18 -0
- package/dist/src/localizations/getLocalizationTable.d.ts +3 -0
- package/dist/src/localizations/getLocalizationTable.js +43 -0
- package/dist/src/rendering/caching/RenderingCacheNode.js +5 -1
- package/dist/src/toolbar/HTMLToolbar.d.ts +1 -0
- package/dist/src/toolbar/HTMLToolbar.js +10 -8
- package/dist/src/toolbar/icons.js +13 -13
- package/dist/src/toolbar/localization.d.ts +1 -0
- package/dist/src/toolbar/localization.js +1 -0
- package/dist/src/toolbar/makeColorInput.js +22 -8
- package/dist/src/toolbar/widgets/BaseWidget.js +29 -0
- package/dist/src/tools/BaseTool.d.ts +2 -1
- package/dist/src/tools/BaseTool.js +3 -0
- package/dist/src/tools/PanZoom.d.ts +2 -1
- package/dist/src/tools/PanZoom.js +4 -0
- package/dist/src/tools/SelectionTool.d.ts +9 -2
- package/dist/src/tools/SelectionTool.js +131 -19
- package/dist/src/tools/ToolController.js +6 -2
- package/dist/src/tools/localization.d.ts +1 -0
- package/dist/src/tools/localization.js +1 -0
- package/dist/src/types.d.ts +8 -2
- package/dist/src/types.js +1 -0
- package/package.json +9 -1
- package/src/Editor.ts +36 -14
- package/src/EditorImage.test.ts +1 -1
- package/src/UndoRedoHistory.ts +4 -0
- package/src/bundle/bundled.ts +2 -1
- package/src/components/builders/RectangleBuilder.ts +23 -8
- package/src/geometry/LineSegment2.test.ts +15 -0
- package/src/geometry/LineSegment2.ts +20 -0
- package/src/geometry/Rect2.test.ts +20 -7
- package/src/geometry/Rect2.ts +19 -1
- package/src/localizations/en.ts +8 -0
- package/src/localizations/es.ts +60 -0
- package/src/localizations/getLocalizationTable.test.ts +27 -0
- package/src/localizations/getLocalizationTable.ts +53 -0
- package/src/rendering/caching/RenderingCacheNode.ts +6 -1
- package/src/toolbar/HTMLToolbar.ts +11 -9
- package/src/toolbar/icons.ts +13 -13
- package/src/toolbar/localization.ts +2 -0
- package/src/toolbar/makeColorInput.ts +25 -10
- package/src/toolbar/toolbar.css +5 -0
- package/src/toolbar/widgets/BaseWidget.ts +34 -0
- package/src/tools/BaseTool.ts +5 -1
- package/src/tools/PanZoom.ts +6 -0
- package/src/tools/SelectionTool.test.ts +24 -1
- package/src/tools/SelectionTool.ts +158 -23
- package/src/tools/ToolController.ts +6 -2
- package/src/tools/localization.ts +2 -0
- package/src/types.ts +9 -1
- package/dist-test/test-dist-bundle.html +0 -42
@@ -8,7 +8,8 @@ import Mat33 from '../geometry/Mat33';
|
|
8
8
|
import Rect2 from '../geometry/Rect2';
|
9
9
|
import { Point2, Vec2 } from '../geometry/Vec2';
|
10
10
|
import { EditorLocalization } from '../localization';
|
11
|
-
import { EditorEventType, PointerEvt } from '../types';
|
11
|
+
import { EditorEventType, KeyPressEvent, KeyUpEvent, PointerEvt } from '../types';
|
12
|
+
import Viewport from '../Viewport';
|
12
13
|
import BaseTool from './BaseTool';
|
13
14
|
import { ToolType } from './ToolController';
|
14
15
|
|
@@ -163,15 +164,15 @@ class Selection {
|
|
163
164
|
|
164
165
|
makeDraggable(draggableBackground, (deltaPosition: Vec2) => {
|
165
166
|
this.handleBackgroundDrag(deltaPosition);
|
166
|
-
}, () => this.
|
167
|
+
}, () => this.finalizeTransform());
|
167
168
|
|
168
169
|
makeDraggable(resizeCorner, (deltaPosition) => {
|
169
170
|
this.handleResizeCornerDrag(deltaPosition);
|
170
|
-
}, () => this.
|
171
|
+
}, () => this.finalizeTransform());
|
171
172
|
|
172
173
|
makeDraggable(this.rotateCircle, (_deltaPosition, offset) => {
|
173
174
|
this.handleRotateCircleDrag(offset);
|
174
|
-
}, () => this.
|
175
|
+
}, () => this.finalizeTransform());
|
175
176
|
}
|
176
177
|
|
177
178
|
// Note a small change in the position of this' background while dragging
|
@@ -186,10 +187,7 @@ class Selection {
|
|
186
187
|
// Snap position to a multiple of 10 (additional decimal points lead to larger files).
|
187
188
|
deltaPosition = this.editor.viewport.roundPoint(deltaPosition);
|
188
189
|
|
189
|
-
this.
|
190
|
-
this.transform = this.transform.rightMul(Mat33.translation(deltaPosition));
|
191
|
-
|
192
|
-
this.previewTransformCmds();
|
190
|
+
this.transformPreview(Mat33.translation(deltaPosition));
|
193
191
|
}
|
194
192
|
|
195
193
|
public handleResizeCornerDrag(deltaPosition: Vec2) {
|
@@ -203,21 +201,13 @@ class Selection {
|
|
203
201
|
const newSize = this.region.size.plus(deltaPosition);
|
204
202
|
|
205
203
|
if (newSize.y > 0 && newSize.x > 0) {
|
206
|
-
|
207
|
-
const scaleFactor = Vec2.of(this.region.w / oldWidth, this.region.h / oldHeight);
|
204
|
+
const scaleFactor = Vec2.of(newSize.x / oldWidth, newSize.y / oldHeight);
|
208
205
|
|
209
|
-
|
210
|
-
this.transform = this.transform.rightMul(currentTransfm);
|
211
|
-
this.previewTransformCmds();
|
206
|
+
this.transformPreview(Mat33.scaling2D(scaleFactor, this.region.topLeft));
|
212
207
|
}
|
213
208
|
}
|
214
209
|
|
215
210
|
public handleRotateCircleDrag(offset: Vec2) {
|
216
|
-
this.boxRotation = this.boxRotation % (2 * Math.PI);
|
217
|
-
if (this.boxRotation < 0) {
|
218
|
-
this.boxRotation += 2 * Math.PI;
|
219
|
-
}
|
220
|
-
|
221
211
|
let targetRotation = offset.angle();
|
222
212
|
targetRotation = targetRotation % (2 * Math.PI);
|
223
213
|
if (targetRotation < 0) {
|
@@ -237,9 +227,7 @@ class Selection {
|
|
237
227
|
deltaRotation *= rotationDirection;
|
238
228
|
}
|
239
229
|
|
240
|
-
this.
|
241
|
-
this.boxRotation += deltaRotation;
|
242
|
-
this.previewTransformCmds();
|
230
|
+
this.transformPreview(Mat33.zRotation(deltaRotation, this.region.center));
|
243
231
|
}
|
244
232
|
|
245
233
|
private computeTransformCommands() {
|
@@ -248,8 +236,29 @@ class Selection {
|
|
248
236
|
});
|
249
237
|
}
|
250
238
|
|
239
|
+
// Applies, previews, but doesn't finalize the given transformation.
|
240
|
+
public transformPreview(transform: Mat33) {
|
241
|
+
this.transform = this.transform.rightMul(transform);
|
242
|
+
const deltaRotation = transform.transformVec3(Vec2.unitX).angle();
|
243
|
+
transform = transform.rightMul(Mat33.zRotation(-deltaRotation, this.region.center));
|
244
|
+
|
245
|
+
this.boxRotation += deltaRotation;
|
246
|
+
this.boxRotation = this.boxRotation % (2 * Math.PI);
|
247
|
+
if (this.boxRotation < 0) {
|
248
|
+
this.boxRotation += 2 * Math.PI;
|
249
|
+
}
|
250
|
+
|
251
|
+
const newSize = transform.transformVec3(this.region.size);
|
252
|
+
const translation = transform.transformVec2(this.region.topLeft).minus(this.region.topLeft);
|
253
|
+
this.region = this.region.resizedTo(newSize);
|
254
|
+
this.region = this.region.translatedBy(translation);
|
255
|
+
|
256
|
+
this.previewTransformCmds();
|
257
|
+
this.scrollTo();
|
258
|
+
}
|
259
|
+
|
251
260
|
// Applies the current transformation to the selection
|
252
|
-
public
|
261
|
+
public finalizeTransform() {
|
253
262
|
this.transformationCommands.forEach(cmd => {
|
254
263
|
cmd.unapply(this.editor);
|
255
264
|
});
|
@@ -321,7 +330,6 @@ class Selection {
|
|
321
330
|
this.updateUI();
|
322
331
|
}
|
323
332
|
|
324
|
-
|
325
333
|
public appendBackgroundBoxTo(elem: HTMLElement) {
|
326
334
|
if (this.backgroundBox.parentElement) {
|
327
335
|
this.backgroundBox.remove();
|
@@ -444,6 +452,19 @@ class Selection {
|
|
444
452
|
this.rotateCircle.style.transform = `rotate(${-rotationDeg}deg)`;
|
445
453
|
}
|
446
454
|
|
455
|
+
// Scroll the viewport to this. Does not zoom
|
456
|
+
public scrollTo() {
|
457
|
+
const viewport = this.editor.viewport;
|
458
|
+
const visibleRect = viewport.visibleRect;
|
459
|
+
if (!visibleRect.containsPoint(this.region.center)) {
|
460
|
+
const closestPoint = visibleRect.getClosestPointOnBoundaryTo(this.region.center);
|
461
|
+
const delta = this.region.center.minus(closestPoint);
|
462
|
+
this.editor.dispatchNoAnnounce(
|
463
|
+
new Viewport.ViewportTransform(Mat33.translation(delta.times(-1))), false
|
464
|
+
);
|
465
|
+
}
|
466
|
+
}
|
467
|
+
|
447
468
|
public deleteSelectedObjects(): Command {
|
448
469
|
return new Erase(this.selectedElems);
|
449
470
|
}
|
@@ -473,6 +494,8 @@ export default class SelectionTool extends BaseTool {
|
|
473
494
|
this.selectionBox?.recomputeRegion();
|
474
495
|
this.selectionBox?.updateUI();
|
475
496
|
});
|
497
|
+
|
498
|
+
this.editor.handleKeyEventsFrom(this.handleOverlay);
|
476
499
|
}
|
477
500
|
|
478
501
|
public onPointerDown(event: PointerEvt): boolean {
|
@@ -512,7 +535,12 @@ export default class SelectionTool extends BaseTool {
|
|
512
535
|
this.editor.announceForAccessibility(
|
513
536
|
this.editor.localization.selectedElements(this.selectionBox.getSelectedItemCount())
|
514
537
|
);
|
538
|
+
this.zoomToSelection();
|
539
|
+
}
|
540
|
+
}
|
515
541
|
|
542
|
+
private zoomToSelection() {
|
543
|
+
if (this.selectionBox) {
|
516
544
|
const selectionRect = this.selectionBox.region;
|
517
545
|
this.editor.dispatchNoAnnounce(this.editor.viewport.zoomTo(selectionRect, false), false);
|
518
546
|
}
|
@@ -532,6 +560,106 @@ export default class SelectionTool extends BaseTool {
|
|
532
560
|
this.selectionBox?.appendBackgroundBoxTo(this.handleOverlay);
|
533
561
|
}
|
534
562
|
|
563
|
+
private static handleableKeys = [
|
564
|
+
'a', 'h', 'ArrowLeft',
|
565
|
+
'd', 'l', 'ArrowRight',
|
566
|
+
'q', 'k', 'ArrowUp',
|
567
|
+
'e', 'j', 'ArrowDown',
|
568
|
+
'r', 'R',
|
569
|
+
'i', 'I', 'o', 'O',
|
570
|
+
];
|
571
|
+
public onKeyPress(event: KeyPressEvent): boolean {
|
572
|
+
let rotationSteps = 0;
|
573
|
+
let xTranslateSteps = 0;
|
574
|
+
let yTranslateSteps = 0;
|
575
|
+
let xScaleSteps = 0;
|
576
|
+
let yScaleSteps = 0;
|
577
|
+
|
578
|
+
switch (event.key) {
|
579
|
+
case 'a':
|
580
|
+
case 'h':
|
581
|
+
case 'ArrowLeft':
|
582
|
+
xTranslateSteps -= 1;
|
583
|
+
break;
|
584
|
+
case 'd':
|
585
|
+
case 'l':
|
586
|
+
case 'ArrowRight':
|
587
|
+
xTranslateSteps += 1;
|
588
|
+
break;
|
589
|
+
case 'q':
|
590
|
+
case 'k':
|
591
|
+
case 'ArrowUp':
|
592
|
+
yTranslateSteps -= 1;
|
593
|
+
break;
|
594
|
+
case 'e':
|
595
|
+
case 'j':
|
596
|
+
case 'ArrowDown':
|
597
|
+
yTranslateSteps += 1;
|
598
|
+
break;
|
599
|
+
case 'r':
|
600
|
+
rotationSteps += 1;
|
601
|
+
break;
|
602
|
+
case 'R':
|
603
|
+
rotationSteps -= 1;
|
604
|
+
break;
|
605
|
+
case 'i':
|
606
|
+
xScaleSteps -= 1;
|
607
|
+
break;
|
608
|
+
case 'I':
|
609
|
+
xScaleSteps += 1;
|
610
|
+
break;
|
611
|
+
case 'o':
|
612
|
+
yScaleSteps -= 1;
|
613
|
+
break;
|
614
|
+
case 'O':
|
615
|
+
yScaleSteps += 1;
|
616
|
+
break;
|
617
|
+
}
|
618
|
+
|
619
|
+
let handled = xTranslateSteps !== 0
|
620
|
+
|| yTranslateSteps !== 0
|
621
|
+
|| rotationSteps !== 0
|
622
|
+
|| xScaleSteps !== 0
|
623
|
+
|| yScaleSteps !== 0;
|
624
|
+
|
625
|
+
if (!this.selectionBox) {
|
626
|
+
handled = false;
|
627
|
+
} else if (handled) {
|
628
|
+
const translateStepSize = 10 * this.editor.viewport.getSizeOfPixelOnCanvas();
|
629
|
+
const rotateStepSize = Math.PI / 8;
|
630
|
+
const scaleStepSize = translateStepSize / 2;
|
631
|
+
|
632
|
+
const region = this.selectionBox.region;
|
633
|
+
const scaledSize = this.selectionBox.region.size.plus(
|
634
|
+
Vec2.of(xScaleSteps, yScaleSteps).times(scaleStepSize)
|
635
|
+
);
|
636
|
+
|
637
|
+
const transform = Mat33.scaling2D(
|
638
|
+
Vec2.of(
|
639
|
+
// Don't more-than-half the size of the selection
|
640
|
+
Math.max(0.5, scaledSize.x / region.size.x),
|
641
|
+
Math.max(0.5, scaledSize.y / region.size.y)
|
642
|
+
),
|
643
|
+
region.topLeft
|
644
|
+
).rightMul(Mat33.zRotation(
|
645
|
+
rotationSteps * rotateStepSize, region.center
|
646
|
+
)).rightMul(Mat33.translation(
|
647
|
+
Vec2.of(xTranslateSteps, yTranslateSteps).times(translateStepSize)
|
648
|
+
));
|
649
|
+
this.selectionBox.transformPreview(transform);
|
650
|
+
}
|
651
|
+
|
652
|
+
return handled;
|
653
|
+
}
|
654
|
+
|
655
|
+
public onKeyUp(evt: KeyUpEvent) {
|
656
|
+
if (this.selectionBox && SelectionTool.handleableKeys.some(key => key === evt.key)) {
|
657
|
+
this.selectionBox.finalizeTransform();
|
658
|
+
return true;
|
659
|
+
}
|
660
|
+
return false;
|
661
|
+
}
|
662
|
+
|
535
663
|
public setEnabled(enabled: boolean) {
|
536
664
|
super.setEnabled(enabled);
|
537
665
|
|
@@ -540,6 +668,13 @@ export default class SelectionTool extends BaseTool {
|
|
540
668
|
this.selectionBox = null;
|
541
669
|
|
542
670
|
this.handleOverlay.style.display = enabled ? 'block' : 'none';
|
671
|
+
|
672
|
+
if (enabled) {
|
673
|
+
this.handleOverlay.tabIndex = 0;
|
674
|
+
this.handleOverlay.ariaLabel = this.editor.localization.selectionToolKeyboardShortcuts;
|
675
|
+
} else {
|
676
|
+
this.handleOverlay.tabIndex = -1;
|
677
|
+
}
|
543
678
|
}
|
544
679
|
|
545
680
|
// Get the object responsible for displaying this' selection.
|
@@ -30,6 +30,7 @@ export default class ToolController {
|
|
30
30
|
public constructor(editor: Editor, localization: ToolLocalization) {
|
31
31
|
const primaryToolEnabledGroup = new ToolEnabledGroup();
|
32
32
|
const panZoomTool = new PanZoom(editor, PanZoomMode.TwoFingerTouchGestures | PanZoomMode.RightClickDrags, localization.touchPanTool);
|
33
|
+
const keyboardPanZoomTool = new PanZoom(editor, PanZoomMode.Keyboard, localization.keyboardPanZoom);
|
33
34
|
const primaryPenTool = new Pen(editor, localization.penTool(1), { color: Color4.purple, thickness: 16 });
|
34
35
|
const primaryTools = [
|
35
36
|
new SelectionTool(editor, localization.selectionTool),
|
@@ -48,6 +49,7 @@ export default class ToolController {
|
|
48
49
|
new PipetteTool(editor, localization.pipetteTool),
|
49
50
|
panZoomTool,
|
50
51
|
...primaryTools,
|
52
|
+
keyboardPanZoomTool,
|
51
53
|
new UndoRedoShortcut(editor),
|
52
54
|
];
|
53
55
|
primaryTools.forEach(tool => tool.setToolGroup(primaryToolEnabledGroup));
|
@@ -88,9 +90,10 @@ export default class ToolController {
|
|
88
90
|
this.activeTool = null;
|
89
91
|
handled = true;
|
90
92
|
} else if (
|
91
|
-
event.kind === InputEvtType.WheelEvt || event.kind === InputEvtType.KeyPressEvent
|
93
|
+
event.kind === InputEvtType.WheelEvt || event.kind === InputEvtType.KeyPressEvent || event.kind === InputEvtType.KeyUpEvent
|
92
94
|
) {
|
93
95
|
const isKeyPressEvt = event.kind === InputEvtType.KeyPressEvent;
|
96
|
+
const isKeyReleaseEvt = event.kind === InputEvtType.KeyUpEvent;
|
94
97
|
const isWheelEvt = event.kind === InputEvtType.WheelEvt;
|
95
98
|
for (const tool of this.tools) {
|
96
99
|
if (!tool.isEnabled()) {
|
@@ -99,7 +102,8 @@ export default class ToolController {
|
|
99
102
|
|
100
103
|
const wheelResult = isWheelEvt && tool.onWheel(event);
|
101
104
|
const keyPressResult = isKeyPressEvt && tool.onKeyPress(event);
|
102
|
-
|
105
|
+
const keyReleaseResult = isKeyReleaseEvt && tool.onKeyUp(event);
|
106
|
+
handled = keyPressResult || wheelResult || keyReleaseResult;
|
103
107
|
|
104
108
|
if (handled) {
|
105
109
|
break;
|
@@ -1,5 +1,6 @@
|
|
1
1
|
|
2
2
|
export interface ToolLocalization {
|
3
|
+
keyboardPanZoom: string;
|
3
4
|
penTool: (penId: number)=>string;
|
4
5
|
selectionTool: string;
|
5
6
|
eraserTool: string;
|
@@ -25,6 +26,7 @@ export const defaultToolLocalization: ToolLocalization = {
|
|
25
26
|
undoRedoTool: 'Undo/Redo',
|
26
27
|
rightClickDragPanTool: 'Right-click drag',
|
27
28
|
pipetteTool: 'Pick color from screen',
|
29
|
+
keyboardPanZoom: 'Keyboard pan/zoom shortcuts',
|
28
30
|
|
29
31
|
textTool: 'Text',
|
30
32
|
enterTextToInsert: 'Text to insert',
|
package/src/types.ts
CHANGED
@@ -24,6 +24,7 @@ export interface PointerEvtListener {
|
|
24
24
|
onGestureCancel(): void;
|
25
25
|
}
|
26
26
|
|
27
|
+
|
27
28
|
export enum InputEvtType {
|
28
29
|
PointerDownEvt,
|
29
30
|
PointerMoveEvt,
|
@@ -32,6 +33,7 @@ export enum InputEvtType {
|
|
32
33
|
|
33
34
|
WheelEvt,
|
34
35
|
KeyPressEvent,
|
36
|
+
KeyUpEvent
|
35
37
|
}
|
36
38
|
|
37
39
|
// [delta.x] is horizontal scroll,
|
@@ -49,6 +51,12 @@ export interface KeyPressEvent {
|
|
49
51
|
readonly ctrlKey: boolean;
|
50
52
|
}
|
51
53
|
|
54
|
+
export interface KeyUpEvent {
|
55
|
+
readonly kind: InputEvtType.KeyUpEvent;
|
56
|
+
readonly key: string;
|
57
|
+
readonly ctrlKey: boolean;
|
58
|
+
}
|
59
|
+
|
52
60
|
// Event triggered when pointer capture is taken by a different [PointerEvtListener].
|
53
61
|
export interface GestureCancelEvt {
|
54
62
|
readonly kind: InputEvtType.GestureCancelEvt;
|
@@ -72,7 +80,7 @@ export interface PointerUpEvt extends PointerEvtBase {
|
|
72
80
|
}
|
73
81
|
|
74
82
|
export type PointerEvt = PointerDownEvt | PointerMoveEvt | PointerUpEvt;
|
75
|
-
export type InputEvt = KeyPressEvent | WheelEvt | GestureCancelEvt | PointerEvt;
|
83
|
+
export type InputEvt = KeyPressEvent | KeyUpEvent | WheelEvt | GestureCancelEvt | PointerEvt;
|
76
84
|
|
77
85
|
export type EditorNotifier = EventDispatcher<EditorEventType, EditorEventDataType>;
|
78
86
|
|
@@ -1,42 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
|
5
|
-
<meta charset="utf-8"/>
|
6
|
-
<title>Editor from a bundle</title>
|
7
|
-
<style>
|
8
|
-
body .imageEditorContainer {
|
9
|
-
height: 800px;
|
10
|
-
|
11
|
-
--primary-background-color: green;
|
12
|
-
--primary-background-color-transparent: rgba(255, 240, 200, 0.5);
|
13
|
-
--secondary-background-color: yellow;
|
14
|
-
--primary-foreground-color: black;
|
15
|
-
--secondary-foreground-color: black;
|
16
|
-
}
|
17
|
-
</style>
|
18
|
-
</head>
|
19
|
-
<body>
|
20
|
-
<p>
|
21
|
-
This file tests the bundled version of <code>js-draw</code>.
|
22
|
-
Be sure to run <code>yarn build</code> before opening this!
|
23
|
-
</p>
|
24
|
-
<script src="../dist/bundle.js"></script>
|
25
|
-
<script>
|
26
|
-
const editor1 = new jsdraw.Editor(document.body, {
|
27
|
-
wheelEventsEnabled: false,
|
28
|
-
});
|
29
|
-
editor1.addToolbar();
|
30
|
-
editor1.loadFromSVG('<svg><text>Wheel events disabled.</text></svg>');
|
31
|
-
|
32
|
-
const editor2 = new jsdraw.Editor(document.body, {
|
33
|
-
wheelEventsEnabled: 'only-if-focused',
|
34
|
-
});
|
35
|
-
editor2.addToolbar();
|
36
|
-
editor2.loadFromSVG('<svg><text>Wheel events enabled, only if focused.</text></svg>');
|
37
|
-
|
38
|
-
const editor3 = new jsdraw.Editor(document.body);
|
39
|
-
editor3.addToolbar();
|
40
|
-
</script>
|
41
|
-
</body>
|
42
|
-
</html>
|