@leafer-ui/core 1.0.0-rc.9 → 1.0.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.
@@ -0,0 +1,1571 @@
1
+ import { Leafer, State, UI, ImageManager, Rect, Group } from '@leafer-ui/draw';
2
+ export * from '@leafer-ui/draw';
3
+ import { registerUI, Creator, PropertyEvent, Debug, DataHelper, canvasSizeAttrs, LayoutEvent, RenderEvent, Event, EventCreator, registerUIEvent, LeafList, BoundsHelper, PointHelper, Bounds, ResizeEvent, LeaferEvent, CanvasManager, Leaf, Matrix, Platform, tempBounds, LeaferCanvasBase } from '@leafer/core';
4
+
5
+ /******************************************************************************
6
+ Copyright (c) Microsoft Corporation.
7
+
8
+ Permission to use, copy, modify, and/or distribute this software for any
9
+ purpose with or without fee is hereby granted.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17
+ PERFORMANCE OF THIS SOFTWARE.
18
+ ***************************************************************************** */
19
+ /* global Reflect, Promise, SuppressedError, Symbol */
20
+
21
+
22
+ function __decorate(decorators, target, key, desc) {
23
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
24
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
25
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
26
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
27
+ }
28
+
29
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
30
+ var e = new Error(message);
31
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
32
+ };
33
+
34
+ let App = class App extends Leafer {
35
+ get __tag() { return 'App'; }
36
+ get isApp() { return true; }
37
+ constructor(userConfig, data) {
38
+ super(userConfig, data);
39
+ }
40
+ init(userConfig, parentApp) {
41
+ super.init(userConfig, parentApp);
42
+ if (userConfig) {
43
+ const { ground, tree, sky, editor } = userConfig;
44
+ if (ground)
45
+ this.ground = this.addLeafer(ground);
46
+ if (tree || editor)
47
+ this.tree = this.addLeafer(tree);
48
+ if (sky || editor)
49
+ this.sky = this.addLeafer(sky || { type: 'draw', usePartRender: false });
50
+ if (editor) {
51
+ this.editor = Creator.editor(editor);
52
+ this.sky.add(this.editor);
53
+ }
54
+ }
55
+ }
56
+ __setApp() {
57
+ const { canvas } = this;
58
+ const { realCanvas, view } = this.config;
59
+ if (realCanvas || view === this.canvas.view || !canvas.parentView) {
60
+ this.realCanvas = true;
61
+ }
62
+ else {
63
+ canvas.unrealCanvas();
64
+ }
65
+ this.leafer = this;
66
+ this.watcher.disable();
67
+ this.layouter.disable();
68
+ this.__eventIds.push(this.on_(PropertyEvent.CHANGE, this.__onPropertyChange, this));
69
+ }
70
+ start() {
71
+ super.start();
72
+ this.children.forEach(leafer => leafer.start());
73
+ }
74
+ stop() {
75
+ this.children.forEach(leafer => leafer.stop());
76
+ super.stop();
77
+ }
78
+ unlockLayout() {
79
+ super.unlockLayout();
80
+ this.children.forEach(leafer => leafer.unlockLayout());
81
+ }
82
+ lockLayout() {
83
+ super.lockLayout();
84
+ this.children.forEach(leafer => leafer.lockLayout());
85
+ }
86
+ forceRender(bounds) {
87
+ this.children.forEach(leafer => leafer.forceRender(bounds));
88
+ }
89
+ addLeafer(merge) {
90
+ const leafer = new Leafer(merge);
91
+ this.add(leafer);
92
+ return leafer;
93
+ }
94
+ add(leafer, index) {
95
+ if (!leafer.view) {
96
+ if (this.realCanvas && !this.canvas.bounds) {
97
+ setTimeout(() => this.add(leafer, index), 10);
98
+ return;
99
+ }
100
+ leafer.init(this.__getChildConfig(leafer.userConfig), this);
101
+ }
102
+ super.add(leafer, index);
103
+ if (index !== undefined)
104
+ leafer.canvas.childIndex = index;
105
+ this.__listenChildEvents(leafer);
106
+ }
107
+ __onPropertyChange() {
108
+ if (Debug.showHitView)
109
+ this.children.forEach(leafer => leafer.forceUpdate('surface'));
110
+ }
111
+ __onCreated() {
112
+ this.created = this.children.every(child => child.created);
113
+ }
114
+ __onReady() {
115
+ if (this.children.every(child => child.ready))
116
+ super.__onReady();
117
+ }
118
+ __onViewReady() {
119
+ if (this.children.every(child => child.viewReady))
120
+ super.__onViewReady();
121
+ }
122
+ __onChildRenderEnd(e) {
123
+ this.renderer.addBlock(e.renderBounds);
124
+ if (this.viewReady)
125
+ this.renderer.update();
126
+ }
127
+ __render(canvas, options) {
128
+ if (canvas.context) {
129
+ if (options.matrix) {
130
+ const { a, b, c, d, e, f } = options.matrix;
131
+ canvas.setTransform(a, b, c, d, e, f);
132
+ }
133
+ this.children.forEach(leafer => canvas.copyWorld(leafer.canvas));
134
+ }
135
+ }
136
+ __onResize(event) {
137
+ this.children.forEach(leafer => leafer.resize(event));
138
+ super.__onResize(event);
139
+ }
140
+ __checkUpdateLayout() {
141
+ this.children.forEach(leafer => leafer.__layout.update());
142
+ }
143
+ __getChildConfig(userConfig) {
144
+ let config = Object.assign({}, this.config);
145
+ config.hittable = config.realCanvas = undefined;
146
+ if (userConfig)
147
+ DataHelper.assign(config, userConfig);
148
+ if (this.autoLayout)
149
+ DataHelper.copyAttrs(config, this, canvasSizeAttrs);
150
+ config.view = this.realCanvas ? undefined : this.view;
151
+ config.fill = undefined;
152
+ return config;
153
+ }
154
+ __listenChildEvents(leafer) {
155
+ leafer.once(LayoutEvent.END, () => this.__onReady());
156
+ leafer.once(RenderEvent.START, () => this.__onCreated());
157
+ leafer.once(RenderEvent.END, () => this.__onViewReady());
158
+ if (this.realCanvas)
159
+ this.__eventIds.push(leafer.on_(RenderEvent.END, this.__onChildRenderEnd, this));
160
+ }
161
+ };
162
+ App = __decorate([
163
+ registerUI()
164
+ ], App);
165
+
166
+ const downKeyMap = {};
167
+ const Keyboard = {
168
+ isHoldSpaceKey() {
169
+ return Keyboard.isHold('Space');
170
+ },
171
+ isHold(code) {
172
+ return downKeyMap[code];
173
+ },
174
+ setDownCode(code) {
175
+ if (!downKeyMap[code])
176
+ downKeyMap[code] = true;
177
+ },
178
+ setUpCode(code) {
179
+ downKeyMap[code] = false;
180
+ }
181
+ };
182
+
183
+ const PointerButton = {
184
+ LEFT: 1,
185
+ RIGHT: 2,
186
+ MIDDLE: 4,
187
+ defaultLeft(event) { if (!event.buttons)
188
+ event.buttons = 1; },
189
+ left(event) { return event.buttons === 1; },
190
+ right(event) { return event.buttons === 2; },
191
+ middle(event) { return event.buttons === 4; }
192
+ };
193
+
194
+ class UIEvent extends Event {
195
+ get spaceKey() { return Keyboard.isHoldSpaceKey(); }
196
+ get left() { return PointerButton.left(this); }
197
+ get right() { return PointerButton.right(this); }
198
+ get middle() { return PointerButton.middle(this); }
199
+ constructor(params) {
200
+ super(params.type);
201
+ this.bubbles = true;
202
+ Object.assign(this, params);
203
+ }
204
+ getPage() {
205
+ return this.current.getPagePoint(this);
206
+ }
207
+ getInner(relative) {
208
+ if (!relative)
209
+ relative = this.current;
210
+ return relative.getInnerPoint(this);
211
+ }
212
+ getLocal(relative) {
213
+ if (!relative)
214
+ relative = this.current;
215
+ return relative.getLocalPoint(this);
216
+ }
217
+ static changeName(oldName, newName) {
218
+ EventCreator.changeName(oldName, newName);
219
+ }
220
+ }
221
+
222
+ let PointerEvent = class PointerEvent extends UIEvent {
223
+ };
224
+ PointerEvent.POINTER = 'pointer';
225
+ PointerEvent.BEFORE_DOWN = 'pointer.before_down';
226
+ PointerEvent.BEFORE_MOVE = 'pointer.before_move';
227
+ PointerEvent.BEFORE_UP = 'pointer.before_up';
228
+ PointerEvent.DOWN = 'pointer.down';
229
+ PointerEvent.MOVE = 'pointer.move';
230
+ PointerEvent.UP = 'pointer.up';
231
+ PointerEvent.OVER = 'pointer.over';
232
+ PointerEvent.OUT = 'pointer.out';
233
+ PointerEvent.ENTER = 'pointer.enter';
234
+ PointerEvent.LEAVE = 'pointer.leave';
235
+ PointerEvent.TAP = 'tap';
236
+ PointerEvent.DOUBLE_TAP = 'double_tap';
237
+ PointerEvent.CLICK = 'click';
238
+ PointerEvent.DOUBLE_CLICK = 'double_click';
239
+ PointerEvent.LONG_PRESS = 'long_press';
240
+ PointerEvent.LONG_TAP = 'long_tap';
241
+ PointerEvent.MENU = 'pointer.menu';
242
+ PointerEvent.MENU_TAP = 'pointer.menu_tap';
243
+ PointerEvent = __decorate([
244
+ registerUIEvent()
245
+ ], PointerEvent);
246
+
247
+ const move = {};
248
+ let DragEvent = class DragEvent extends PointerEvent {
249
+ static setList(data) {
250
+ this.list = data instanceof LeafList ? data : new LeafList(data);
251
+ }
252
+ static setData(data) {
253
+ this.data = data;
254
+ }
255
+ static getValidMove(leaf, start, total) {
256
+ const { draggable, dragBounds, x, y } = leaf;
257
+ const move = leaf.getLocalPoint(total, null, true);
258
+ move.x += start.x - x;
259
+ move.y += start.y - y;
260
+ if (dragBounds)
261
+ this.getMoveInDragBounds(leaf.__local, dragBounds === 'parent' ? leaf.parent.boxBounds : dragBounds, move, true);
262
+ if (draggable === 'x')
263
+ move.y = 0;
264
+ if (draggable === 'y')
265
+ move.x = 0;
266
+ return move;
267
+ }
268
+ static getMoveInDragBounds(childBox, dragBounds, move, change) {
269
+ const x = childBox.x + move.x, y = childBox.y + move.y;
270
+ const right = x + childBox.width, bottom = y + childBox.height;
271
+ const boundsRight = dragBounds.x + dragBounds.width, boundsBottom = dragBounds.y + dragBounds.height;
272
+ if (!change)
273
+ move = Object.assign({}, move);
274
+ if (BoundsHelper.includes(childBox, dragBounds)) {
275
+ if (x > dragBounds.x)
276
+ move.x += dragBounds.x - x;
277
+ else if (right < boundsRight)
278
+ move.x += boundsRight - right;
279
+ if (y > dragBounds.y)
280
+ move.y += dragBounds.y - y;
281
+ else if (bottom < boundsBottom)
282
+ move.y += boundsBottom - bottom;
283
+ }
284
+ else {
285
+ if (x < dragBounds.x)
286
+ move.x += dragBounds.x - x;
287
+ else if (right > boundsRight)
288
+ move.x += boundsRight - right;
289
+ if (y < dragBounds.y)
290
+ move.y += dragBounds.y - y;
291
+ else if (bottom > boundsBottom)
292
+ move.y += boundsBottom - bottom;
293
+ }
294
+ return move;
295
+ }
296
+ getPageMove(total) {
297
+ this.assignMove(total);
298
+ return this.current.getPagePoint(move, null, true);
299
+ }
300
+ getInnerMove(relative, total) {
301
+ if (!relative)
302
+ relative = this.current;
303
+ this.assignMove(total);
304
+ return relative.getInnerPoint(move, null, true);
305
+ }
306
+ getLocalMove(relative, total) {
307
+ if (!relative)
308
+ relative = this.current;
309
+ this.assignMove(total);
310
+ return relative.getLocalPoint(move, null, true);
311
+ }
312
+ getPageTotal() {
313
+ return this.getPageMove(true);
314
+ }
315
+ getInnerTotal(relative) {
316
+ return this.getInnerMove(relative, true);
317
+ }
318
+ getLocalTotal(relative) {
319
+ return this.getLocalMove(relative, true);
320
+ }
321
+ getPageBounds() {
322
+ const total = this.getPageTotal();
323
+ const start = this.getPage();
324
+ const bounds = {};
325
+ BoundsHelper.set(bounds, start.x - total.x, start.y - total.y, total.x, total.y);
326
+ BoundsHelper.unsign(bounds);
327
+ return bounds;
328
+ }
329
+ assignMove(total) {
330
+ move.x = total ? this.totalX : this.moveX;
331
+ move.y = total ? this.totalY : this.moveY;
332
+ }
333
+ };
334
+ DragEvent.BEFORE_DRAG = 'drag.before_drag';
335
+ DragEvent.START = 'drag.start';
336
+ DragEvent.DRAG = 'drag';
337
+ DragEvent.END = 'drag.end';
338
+ DragEvent.OVER = 'drag.over';
339
+ DragEvent.OUT = 'drag.out';
340
+ DragEvent.ENTER = 'drag.enter';
341
+ DragEvent.LEAVE = 'drag.leave';
342
+ DragEvent = __decorate([
343
+ registerUIEvent()
344
+ ], DragEvent);
345
+
346
+ let DropEvent = class DropEvent extends PointerEvent {
347
+ static setList(data) {
348
+ DragEvent.setList(data);
349
+ }
350
+ static setData(data) {
351
+ DragEvent.setData(data);
352
+ }
353
+ };
354
+ DropEvent.DROP = 'drop';
355
+ DropEvent = __decorate([
356
+ registerUIEvent()
357
+ ], DropEvent);
358
+
359
+ let MoveEvent = class MoveEvent extends DragEvent {
360
+ };
361
+ MoveEvent.BEFORE_MOVE = 'move.before_move';
362
+ MoveEvent.START = 'move.start';
363
+ MoveEvent.MOVE = 'move';
364
+ MoveEvent.END = 'move.end';
365
+ MoveEvent = __decorate([
366
+ registerUIEvent()
367
+ ], MoveEvent);
368
+
369
+ let RotateEvent = class RotateEvent extends UIEvent {
370
+ };
371
+ RotateEvent.BEFORE_ROTATE = 'rotate.before_rotate';
372
+ RotateEvent.START = 'rotate.start';
373
+ RotateEvent.ROTATE = 'rotate';
374
+ RotateEvent.END = 'rotate.end';
375
+ RotateEvent = __decorate([
376
+ registerUIEvent()
377
+ ], RotateEvent);
378
+
379
+ let SwipeEvent = class SwipeEvent extends DragEvent {
380
+ };
381
+ SwipeEvent.SWIPE = 'swipe';
382
+ SwipeEvent.LEFT = 'swipe.left';
383
+ SwipeEvent.RIGHT = 'swipe.right';
384
+ SwipeEvent.UP = 'swipe.up';
385
+ SwipeEvent.DOWN = 'swipe.down';
386
+ SwipeEvent = __decorate([
387
+ registerUIEvent()
388
+ ], SwipeEvent);
389
+
390
+ let ZoomEvent = class ZoomEvent extends UIEvent {
391
+ };
392
+ ZoomEvent.BEFORE_ZOOM = 'zoom.before_zoom';
393
+ ZoomEvent.START = 'zoom.start';
394
+ ZoomEvent.ZOOM = 'zoom';
395
+ ZoomEvent.END = 'zoom.end';
396
+ ZoomEvent = __decorate([
397
+ registerUIEvent()
398
+ ], ZoomEvent);
399
+
400
+ let KeyEvent = class KeyEvent extends UIEvent {
401
+ };
402
+ KeyEvent.DOWN = 'key.down';
403
+ KeyEvent.HOLD = 'key.hold';
404
+ KeyEvent.UP = 'key.up';
405
+ KeyEvent = __decorate([
406
+ registerUIEvent()
407
+ ], KeyEvent);
408
+
409
+ function addInteractionWindow(leafer) {
410
+ if (leafer.isApp)
411
+ return;
412
+ leafer.__eventIds.push(leafer.on_(MoveEvent.BEFORE_MOVE, (e) => {
413
+ leafer.zoomLayer.move(leafer.getValidMove(e.moveX, e.moveY));
414
+ }), leafer.on_(ZoomEvent.BEFORE_ZOOM, (e) => {
415
+ const { zoomLayer } = leafer;
416
+ const changeScale = leafer.getValidScale(e.scale);
417
+ if (changeScale !== 1) {
418
+ PointHelper.scaleOf(zoomLayer, e, changeScale);
419
+ zoomLayer.scale = zoomLayer.__.scaleX * changeScale;
420
+ }
421
+ }));
422
+ }
423
+
424
+ function document(leafer) {
425
+ addInteractionWindow(leafer);
426
+ leafer.config.move.scroll = 'limit';
427
+ leafer.config.zoom.min = 1;
428
+ }
429
+
430
+ const debug$1 = Debug.get('LeaferTypeCreator');
431
+ const LeaferTypeCreator = {
432
+ list: {},
433
+ register(name, fn) {
434
+ if (list[name]) {
435
+ debug$1.repeat(name);
436
+ }
437
+ else {
438
+ list[name] = fn;
439
+ }
440
+ },
441
+ run(name, leafer) {
442
+ const fn = list[name];
443
+ if (fn) {
444
+ fn(leafer);
445
+ }
446
+ else {
447
+ debug$1.error('no', name);
448
+ }
449
+ }
450
+ };
451
+ const { list, register } = LeaferTypeCreator;
452
+ register('draw', () => { });
453
+ register('custom', () => { });
454
+ register('design', addInteractionWindow);
455
+ register('document', document);
456
+
457
+ const leafer = Leafer.prototype;
458
+ leafer.initType = function (type) {
459
+ LeaferTypeCreator.run(type, this);
460
+ };
461
+ leafer.getValidMove = function (moveX, moveY) {
462
+ const { scroll, disabled } = this.app.config.move;
463
+ if (scroll) {
464
+ if (Math.abs(moveX) > Math.abs(moveY))
465
+ moveY = 0;
466
+ else
467
+ moveX = 0;
468
+ if (scroll === 'limit') {
469
+ const { x, y, width, height } = new Bounds(this.__world).addPoint(this.zoomLayer);
470
+ const right = x + width - this.width, bottom = y + height - this.height;
471
+ if (x >= 0 && right <= 0)
472
+ moveX = 0;
473
+ else if (moveX > 0) {
474
+ if (x + moveX > 0)
475
+ moveX = -x;
476
+ }
477
+ else if (moveX < 0 && right + moveX < 0)
478
+ moveX = -right;
479
+ if (y >= 0 && bottom <= 0)
480
+ moveY = 0;
481
+ else if (moveY > 0) {
482
+ if (y + moveY > 0)
483
+ moveY = -y;
484
+ }
485
+ else if (moveY < 0 && bottom + moveY < 0)
486
+ moveY = -bottom;
487
+ }
488
+ }
489
+ return { x: disabled ? 0 : moveX, y: disabled ? 0 : moveY };
490
+ };
491
+ leafer.getValidScale = function (changeScale) {
492
+ const { scaleX } = this.zoomLayer.__, { min, max, disabled } = this.app.config.zoom, absScale = Math.abs(scaleX * changeScale);
493
+ if (absScale < min)
494
+ changeScale = min / scaleX;
495
+ else if (absScale > max)
496
+ changeScale = max / scaleX;
497
+ return disabled ? 1 : changeScale;
498
+ };
499
+
500
+ class Transformer {
501
+ get transforming() { return !!(this.moveData || this.zoomData || this.rotateData); }
502
+ constructor(interaction) {
503
+ this.interaction = interaction;
504
+ }
505
+ move(data) {
506
+ const { interaction } = this;
507
+ if (!data.moveType)
508
+ data.moveType = 'move';
509
+ if (!this.moveData) {
510
+ const { path } = interaction.selector.getByPoint(data, interaction.hitRadius);
511
+ data.path = path;
512
+ this.moveData = Object.assign(Object.assign({}, data), { moveX: 0, moveY: 0 });
513
+ interaction.cancelHover();
514
+ interaction.emit(MoveEvent.START, this.moveData);
515
+ }
516
+ data.path = this.moveData.path;
517
+ interaction.emit(MoveEvent.BEFORE_MOVE, data);
518
+ interaction.emit(MoveEvent.MOVE, data);
519
+ this.transformEndWait();
520
+ }
521
+ zoom(data) {
522
+ const { interaction } = this;
523
+ if (!this.zoomData) {
524
+ const { path } = interaction.selector.getByPoint(data, interaction.hitRadius);
525
+ data.path = path;
526
+ this.zoomData = Object.assign(Object.assign({}, data), { scale: 1 });
527
+ interaction.cancelHover();
528
+ interaction.emit(ZoomEvent.START, this.zoomData);
529
+ }
530
+ data.path = this.zoomData.path;
531
+ interaction.emit(ZoomEvent.BEFORE_ZOOM, data);
532
+ interaction.emit(ZoomEvent.ZOOM, data);
533
+ this.transformEndWait();
534
+ }
535
+ rotate(data) {
536
+ const { interaction } = this;
537
+ if (!this.rotateData) {
538
+ const { path } = interaction.selector.getByPoint(data, interaction.hitRadius);
539
+ data.path = path;
540
+ this.rotateData = Object.assign(Object.assign({}, data), { rotation: 0 });
541
+ interaction.cancelHover();
542
+ interaction.emit(RotateEvent.START, this.rotateData);
543
+ }
544
+ data.path = this.rotateData.path;
545
+ interaction.emit(RotateEvent.BEFORE_ROTATE, data);
546
+ interaction.emit(RotateEvent.ROTATE, data);
547
+ this.transformEndWait();
548
+ }
549
+ transformEndWait() {
550
+ clearTimeout(this.transformTimer);
551
+ this.transformTimer = setTimeout(() => {
552
+ this.transformEnd();
553
+ }, this.interaction.config.pointer.transformTime);
554
+ }
555
+ transformEnd() {
556
+ this.moveEnd();
557
+ this.zoomEnd();
558
+ this.rotateEnd();
559
+ }
560
+ moveEnd() {
561
+ if (this.moveData) {
562
+ this.interaction.emit(MoveEvent.END, this.moveData);
563
+ this.moveData = null;
564
+ }
565
+ }
566
+ zoomEnd() {
567
+ if (this.zoomData) {
568
+ this.interaction.emit(ZoomEvent.END, this.zoomData);
569
+ this.zoomData = null;
570
+ }
571
+ }
572
+ rotateEnd() {
573
+ if (this.rotateData) {
574
+ this.interaction.emit(RotateEvent.END, this.rotateData);
575
+ this.rotateData = null;
576
+ }
577
+ }
578
+ destroy() {
579
+ this.zoomData = this.moveData = this.rotateData = null;
580
+ }
581
+ }
582
+
583
+ const InteractionHelper = {
584
+ getMoveEventData(center, move, event) {
585
+ return Object.assign(Object.assign({}, event), { x: center.x, y: center.y, moveX: move.x, moveY: move.y });
586
+ },
587
+ getRotateEventData(center, angle, event) {
588
+ return Object.assign(Object.assign({}, event), { x: center.x, y: center.y, rotation: angle });
589
+ },
590
+ getZoomEventData(center, scale, event) {
591
+ return Object.assign(Object.assign({}, event), { x: center.x, y: center.y, scale });
592
+ },
593
+ getDragEventData(startPoint, lastPoint, event) {
594
+ return Object.assign(Object.assign({}, event), { x: event.x, y: event.y, moveX: event.x - lastPoint.x, moveY: event.y - lastPoint.y, totalX: event.x - startPoint.x, totalY: event.y - startPoint.y });
595
+ },
596
+ getDropEventData(event, list, data) {
597
+ return Object.assign(Object.assign({}, event), { list,
598
+ data });
599
+ },
600
+ getSwipeDirection(angle) {
601
+ if (angle < -45 && angle > -135) {
602
+ return SwipeEvent.UP;
603
+ }
604
+ else if (angle > 45 && angle < 135) {
605
+ return SwipeEvent.DOWN;
606
+ }
607
+ else if (angle <= 45 && angle >= -45) {
608
+ return SwipeEvent.RIGHT;
609
+ }
610
+ else {
611
+ return SwipeEvent.LEFT;
612
+ }
613
+ },
614
+ getSwipeEventData(startPoint, lastDragData, event) {
615
+ return Object.assign(Object.assign({}, event), { moveX: lastDragData.moveX, moveY: lastDragData.moveY, totalX: event.x - startPoint.x, totalY: event.y - startPoint.y, type: I.getSwipeDirection(PointHelper.getAngle(startPoint, event)) });
616
+ },
617
+ getBase(e) {
618
+ const pointerUpButtons = e.button === 1 ? 4 : e.button;
619
+ return {
620
+ altKey: e.altKey,
621
+ ctrlKey: e.ctrlKey,
622
+ shiftKey: e.shiftKey,
623
+ metaKey: e.metaKey,
624
+ buttons: e.buttons === undefined ? 1 : (e.buttons === 0 ? pointerUpButtons : e.buttons),
625
+ origin: e
626
+ };
627
+ },
628
+ pathHasEventType(path, type) {
629
+ const { list } = path;
630
+ for (let i = 0, len = list.length; i < len; i++) {
631
+ if (list[i].hasEvent(type))
632
+ return true;
633
+ }
634
+ return false;
635
+ },
636
+ filterPathByEventType(path, type) {
637
+ const find = new LeafList();
638
+ const { list } = path;
639
+ for (let i = 0, len = list.length; i < len; i++) {
640
+ if (list[i].hasEvent(type))
641
+ find.add(list[i]);
642
+ }
643
+ return find;
644
+ }
645
+ };
646
+ const I = InteractionHelper;
647
+
648
+ const emptyList = new LeafList();
649
+ const { getDragEventData, getDropEventData, getSwipeEventData } = InteractionHelper;
650
+ class Dragger {
651
+ constructor(interaction) {
652
+ this.interaction = interaction;
653
+ }
654
+ setDragData(data) {
655
+ if (this.animateWait)
656
+ this.dragEndReal();
657
+ this.downData = this.interaction.downData;
658
+ this.dragData = getDragEventData(data, data, data);
659
+ this.canAnimate = this.canDragOut = true;
660
+ }
661
+ getList() {
662
+ const { proxy } = this.interaction.selector;
663
+ return this.dragging && (!proxy || !proxy.list.length) ? (DragEvent.list || this.dragableList || emptyList) : emptyList;
664
+ }
665
+ checkDrag(data, canDrag) {
666
+ const { interaction } = this;
667
+ if (this.moving && data.buttons < 1) {
668
+ this.canAnimate = false;
669
+ interaction.pointerCancel();
670
+ return;
671
+ }
672
+ if (!this.moving && canDrag) {
673
+ if (this.moving = interaction.canMove(this.downData) || interaction.isHoldRightKey || interaction.isMobileDragEmpty) {
674
+ this.dragData.moveType = 'drag';
675
+ interaction.emit(MoveEvent.START, this.dragData);
676
+ }
677
+ }
678
+ if (!this.moving) {
679
+ this.dragStart(data, canDrag);
680
+ }
681
+ this.drag(data);
682
+ }
683
+ dragStart(data, canDrag) {
684
+ if (!this.dragging) {
685
+ this.dragging = canDrag && PointerButton.left(data);
686
+ if (this.dragging) {
687
+ this.interaction.emit(DragEvent.START, this.dragData);
688
+ this.getDragableList(this.dragData.path);
689
+ this.setDragStartPoints(this.realDragableList = this.getList());
690
+ }
691
+ }
692
+ }
693
+ setDragStartPoints(list) {
694
+ this.dragStartPoints = {};
695
+ list.forEach(leaf => this.dragStartPoints[leaf.innerId] = { x: leaf.x, y: leaf.y });
696
+ }
697
+ getDragableList(path) {
698
+ let leaf;
699
+ for (let i = 0, len = path.length; i < len; i++) {
700
+ leaf = path.list[i];
701
+ if ((leaf.__.draggable || leaf.__.editable) && leaf.__.hitSelf && !leaf.__.locked) {
702
+ this.dragableList = new LeafList(leaf);
703
+ break;
704
+ }
705
+ }
706
+ }
707
+ drag(data) {
708
+ const { interaction, dragData, downData } = this;
709
+ const { path, throughPath } = downData;
710
+ this.dragData = getDragEventData(downData, dragData, data);
711
+ if (throughPath)
712
+ this.dragData.throughPath = throughPath;
713
+ this.dragData.path = path;
714
+ if (this.moving) {
715
+ this.dragData.moveType = 'drag';
716
+ interaction.emit(MoveEvent.BEFORE_MOVE, this.dragData);
717
+ interaction.emit(MoveEvent.MOVE, this.dragData);
718
+ }
719
+ else if (this.dragging) {
720
+ this.dragReal();
721
+ interaction.emit(DragEvent.BEFORE_DRAG, this.dragData);
722
+ interaction.emit(DragEvent.DRAG, this.dragData);
723
+ }
724
+ }
725
+ dragReal() {
726
+ const { running } = this.interaction;
727
+ const list = this.realDragableList;
728
+ if (list.length && running) {
729
+ const { totalX, totalY } = this.dragData;
730
+ list.forEach(leaf => leaf.draggable && leaf.move(DragEvent.getValidMove(leaf, this.dragStartPoints[leaf.innerId], { x: totalX, y: totalY })));
731
+ }
732
+ }
733
+ dragOverOrOut(data) {
734
+ const { interaction } = this;
735
+ const { dragOverPath } = this;
736
+ const { path } = data;
737
+ this.dragOverPath = path;
738
+ if (dragOverPath) {
739
+ if (path.indexAt(0) !== dragOverPath.indexAt(0)) {
740
+ interaction.emit(DragEvent.OUT, data, dragOverPath);
741
+ interaction.emit(DragEvent.OVER, data, path);
742
+ }
743
+ }
744
+ else {
745
+ interaction.emit(DragEvent.OVER, data, path);
746
+ }
747
+ }
748
+ dragEnterOrLeave(data) {
749
+ const { interaction } = this;
750
+ const { dragEnterPath } = this;
751
+ const { path } = data;
752
+ interaction.emit(DragEvent.LEAVE, data, dragEnterPath, path);
753
+ interaction.emit(DragEvent.ENTER, data, path, dragEnterPath);
754
+ this.dragEnterPath = path;
755
+ }
756
+ dragEnd(data, speed) {
757
+ if (!this.dragging && !this.moving)
758
+ return;
759
+ const { moveX, moveY } = this.dragData;
760
+ if (this.interaction.config.move.dragAnimate && this.canAnimate && this.moving && (Math.abs(moveX) > 1 || Math.abs(moveY) > 1)) {
761
+ data = Object.assign({}, data);
762
+ speed = (speed || (data.pointerType === 'touch' ? 2 : 1)) * 0.9;
763
+ PointHelper.move(data, moveX * speed, moveY * speed);
764
+ this.drag(data);
765
+ this.animate(() => { this.dragEnd(data, 1); });
766
+ }
767
+ else {
768
+ this.dragEndReal(data);
769
+ }
770
+ }
771
+ dragEndReal(data) {
772
+ const { interaction, downData, dragData } = this;
773
+ if (!data)
774
+ data = dragData;
775
+ const { path, throughPath } = downData;
776
+ const endDragData = getDragEventData(downData, data, data);
777
+ if (throughPath)
778
+ endDragData.throughPath = throughPath;
779
+ endDragData.path = path;
780
+ if (this.moving) {
781
+ this.moving = false;
782
+ endDragData.moveType = 'drag';
783
+ interaction.emit(MoveEvent.END, endDragData);
784
+ }
785
+ if (this.dragging) {
786
+ const dropList = this.getList();
787
+ this.dragging = false;
788
+ interaction.emit(DragEvent.END, endDragData);
789
+ this.swipe(data, downData, dragData, endDragData);
790
+ this.drop(data, dropList, this.dragEnterPath);
791
+ }
792
+ this.autoMoveCancel();
793
+ this.dragReset();
794
+ this.animate(null, 'off');
795
+ }
796
+ animate(func, off) {
797
+ const animateWait = func || this.animateWait;
798
+ if (animateWait)
799
+ this.interaction.target.nextRender(animateWait, null, off);
800
+ this.animateWait = func;
801
+ }
802
+ swipe(data, downData, dragData, endDragData) {
803
+ const { interaction } = this;
804
+ if (PointHelper.getDistance(downData, data) > interaction.config.pointer.swipeDistance) {
805
+ const swipeData = getSwipeEventData(downData, dragData, endDragData);
806
+ this.interaction.emit(swipeData.type, swipeData);
807
+ }
808
+ }
809
+ drop(data, dropList, dragEnterPath) {
810
+ const dropData = getDropEventData(data, dropList, DragEvent.data);
811
+ dropData.path = dragEnterPath;
812
+ this.interaction.emit(DropEvent.DROP, dropData);
813
+ this.interaction.emit(DragEvent.LEAVE, data, dragEnterPath);
814
+ }
815
+ dragReset() {
816
+ DragEvent.list = DragEvent.data = this.dragableList = this.dragData = this.downData = this.dragOverPath = this.dragEnterPath = null;
817
+ }
818
+ checkDragOut(data) {
819
+ const { interaction } = this;
820
+ this.autoMoveCancel();
821
+ if (this.dragging && !interaction.shrinkCanvasBounds.hitPoint(data))
822
+ this.autoMoveOnDragOut(data);
823
+ }
824
+ autoMoveOnDragOut(data) {
825
+ const { interaction, downData, canDragOut } = this;
826
+ const { autoDistance, dragOut } = interaction.config.move;
827
+ if (!dragOut || !canDragOut || !autoDistance)
828
+ return;
829
+ const bounds = interaction.shrinkCanvasBounds;
830
+ const { x, y } = bounds;
831
+ const right = BoundsHelper.maxX(bounds);
832
+ const bottom = BoundsHelper.maxY(bounds);
833
+ const moveX = data.x < x ? autoDistance : (right < data.x ? -autoDistance : 0);
834
+ const moveY = data.y < y ? autoDistance : (bottom < data.y ? -autoDistance : 0);
835
+ let totalX = 0, totalY = 0;
836
+ this.autoMoveTimer = setInterval(() => {
837
+ totalX += moveX;
838
+ totalY += moveY;
839
+ PointHelper.move(downData, moveX, moveY);
840
+ PointHelper.move(this.dragData, moveX, moveY);
841
+ interaction.move(Object.assign(Object.assign({}, data), { moveX, moveY, totalX, totalY, moveType: 'drag' }));
842
+ interaction.pointerMoveReal(data);
843
+ }, 10);
844
+ }
845
+ autoMoveCancel() {
846
+ if (this.autoMoveTimer) {
847
+ clearInterval(this.autoMoveTimer);
848
+ this.autoMoveTimer = 0;
849
+ }
850
+ }
851
+ destroy() {
852
+ this.dragReset();
853
+ }
854
+ }
855
+
856
+ const debug = Debug.get('emit');
857
+ function emit(type, data, path, excludePath) {
858
+ if (!path && !data.path)
859
+ return;
860
+ let leaf;
861
+ data.type = type;
862
+ if (path) {
863
+ data = Object.assign(Object.assign({}, data), { path });
864
+ }
865
+ else {
866
+ path = data.path;
867
+ }
868
+ data.target = path.indexAt(0);
869
+ try {
870
+ for (let i = path.length - 1; i > -1; i--) {
871
+ leaf = path.list[i];
872
+ if (emitEvent(leaf, type, data, true, excludePath))
873
+ return;
874
+ if (leaf.isApp)
875
+ emitAppChildren(leaf, type, data, true, excludePath);
876
+ }
877
+ for (let i = 0, len = path.length; i < len; i++) {
878
+ leaf = path.list[i];
879
+ if (leaf.isApp)
880
+ emitAppChildren(leaf, type, data, false, excludePath);
881
+ if (emitEvent(leaf, type, data, false, excludePath))
882
+ return;
883
+ }
884
+ }
885
+ catch (e) {
886
+ debug.error(e);
887
+ }
888
+ }
889
+ const allowTypes = ['move', 'zoom', 'rotate', 'key'];
890
+ function emitAppChildren(leaf, type, data, capture, excludePath) {
891
+ if (allowTypes.some(name => type.startsWith(name)) && leaf.__.hitChildren && !exclude(leaf, excludePath)) {
892
+ let child;
893
+ for (let i = 0, len = leaf.children.length; i < len; i++) {
894
+ child = leaf.children[i];
895
+ if (!data.path.has(child) && child.__.hittable)
896
+ emitEvent(child, type, data, capture, excludePath);
897
+ }
898
+ }
899
+ }
900
+ function emitEvent(leaf, type, data, capture, excludePath) {
901
+ if (leaf.destroyed)
902
+ return false;
903
+ if (leaf.__.hitSelf && !exclude(leaf, excludePath)) {
904
+ if (State.updateEventStyle)
905
+ State.updateEventStyle(leaf, type);
906
+ if (leaf.hasEvent(type, capture)) {
907
+ data.phase = capture ? 1 : ((leaf === data.target) ? 2 : 3);
908
+ const event = EventCreator.get(type, data);
909
+ leaf.emitEvent(event, capture);
910
+ if (event.isStop)
911
+ return true;
912
+ }
913
+ }
914
+ return false;
915
+ }
916
+ function exclude(leaf, excludePath) {
917
+ return excludePath && excludePath.has(leaf);
918
+ }
919
+
920
+ const MultiTouchHelper = {
921
+ getData(list) {
922
+ const a = list[0];
923
+ const b = list[1];
924
+ const lastCenter = PointHelper.getCenter(a.from, b.from);
925
+ const center = PointHelper.getCenter(a.to, b.to);
926
+ const move = { x: center.x - lastCenter.x, y: center.y - lastCenter.y };
927
+ const lastDistance = PointHelper.getDistance(a.from, b.from);
928
+ const distance = PointHelper.getDistance(a.to, b.to);
929
+ const scale = distance / lastDistance;
930
+ const angle = PointHelper.getRotation(a.from, b.from, a.to, b.to);
931
+ return { move, scale, angle, center };
932
+ }
933
+ };
934
+
935
+ const config = {
936
+ wheel: {
937
+ zoomSpeed: 0.5,
938
+ moveSpeed: 0.5,
939
+ rotateSpeed: 0.5,
940
+ delta: { x: 80 / 4, y: 8.0 },
941
+ preventDefault: true
942
+ },
943
+ pointer: {
944
+ hitRadius: 5,
945
+ tapTime: 120,
946
+ longPressTime: 800,
947
+ transformTime: 500,
948
+ hover: true,
949
+ dragHover: true,
950
+ dragDistance: 2,
951
+ swipeDistance: 20,
952
+ preventDefaultMenu: true
953
+ },
954
+ cursor: true,
955
+ keyEvent: true
956
+ };
957
+
958
+ const { pathHasEventType, getMoveEventData, getZoomEventData, getRotateEventData } = InteractionHelper;
959
+ class InteractionBase {
960
+ get dragging() { return this.dragger.dragging; }
961
+ get transforming() { return this.transformer.transforming; }
962
+ get moveMode() { return this.config.move.drag || this.isHoldSpaceKey || this.isHoldMiddleKey || (this.isHoldRightKey && this.dragger.moving) || this.isDragEmpty; }
963
+ get canHover() { return this.config.pointer.hover && !this.config.mobile; }
964
+ get isDragEmpty() { return this.config.move.dragEmpty && this.isRootPath(this.hoverData) && (!this.downData || this.isRootPath(this.downData)); }
965
+ get isMobileDragEmpty() { return this.config.move.dragEmpty && !this.canHover && this.downData && this.isTreePath(this.downData); }
966
+ get isHoldMiddleKey() { return this.config.move.holdMiddleKey && this.downData && PointerButton.middle(this.downData); }
967
+ get isHoldRightKey() { return this.config.move.holdRightKey && this.downData && PointerButton.right(this.downData); }
968
+ get isHoldSpaceKey() { return this.config.move.holdSpaceKey && Keyboard.isHoldSpaceKey(); }
969
+ get hitRadius() { return this.config.pointer.hitRadius; }
970
+ constructor(target, canvas, selector, userConfig) {
971
+ this.config = config;
972
+ this.tapCount = 0;
973
+ this.downKeyMap = {};
974
+ this.target = target;
975
+ this.canvas = canvas;
976
+ this.selector = selector;
977
+ this.defaultPath = new LeafList(target);
978
+ this.transformer = new Transformer(this);
979
+ this.dragger = new Dragger(this);
980
+ if (userConfig)
981
+ this.config = DataHelper.default(userConfig, this.config);
982
+ this.__listenEvents();
983
+ }
984
+ start() {
985
+ this.running = true;
986
+ }
987
+ stop() {
988
+ this.running = false;
989
+ }
990
+ receive(_event) { }
991
+ pointerDown(data, useDefaultPath) {
992
+ if (!data)
993
+ data = this.hoverData;
994
+ if (!data)
995
+ return;
996
+ PointerButton.defaultLeft(data);
997
+ this.updateDownData(data);
998
+ this.checkPath(data, useDefaultPath);
999
+ this.downTime = Date.now();
1000
+ this.emit(PointerEvent.BEFORE_DOWN, data);
1001
+ this.emit(PointerEvent.DOWN, data);
1002
+ if (PointerButton.left(data)) {
1003
+ this.tapWait();
1004
+ this.longPressWait(data);
1005
+ }
1006
+ this.waitMenuTap = PointerButton.right(data);
1007
+ this.dragger.setDragData(data);
1008
+ if (!this.isHoldRightKey)
1009
+ this.updateCursor(data);
1010
+ }
1011
+ pointerMove(data) {
1012
+ if (!data)
1013
+ data = this.hoverData;
1014
+ if (!data)
1015
+ return;
1016
+ const { downData } = this;
1017
+ if (downData)
1018
+ PointerButton.defaultLeft(data);
1019
+ const hit = this.canvas.bounds.hitPoint(data);
1020
+ if (hit || downData) {
1021
+ this.pointerMoveReal(data);
1022
+ if (downData)
1023
+ this.dragger.checkDragOut(data);
1024
+ }
1025
+ }
1026
+ pointerMoveReal(data) {
1027
+ const { dragHover, dragDistance } = this.config.pointer;
1028
+ this.emit(PointerEvent.BEFORE_MOVE, data, this.defaultPath);
1029
+ if (this.downData) {
1030
+ const canDrag = PointHelper.getDistance(this.downData, data) > dragDistance;
1031
+ if (canDrag) {
1032
+ if (this.waitTap)
1033
+ this.pointerWaitCancel();
1034
+ this.waitMenuTap = false;
1035
+ }
1036
+ this.dragger.checkDrag(data, canDrag);
1037
+ }
1038
+ if (!this.dragger.moving) {
1039
+ this.updateHoverData(data);
1040
+ this.checkPath(data);
1041
+ this.emit(PointerEvent.MOVE, data);
1042
+ if (!(this.dragging && !dragHover))
1043
+ this.pointerHover(data);
1044
+ if (this.dragger.dragging) {
1045
+ this.dragger.dragOverOrOut(data);
1046
+ this.dragger.dragEnterOrLeave(data);
1047
+ }
1048
+ }
1049
+ this.updateCursor(this.downData || data);
1050
+ }
1051
+ pointerUp(data) {
1052
+ const { downData } = this;
1053
+ if (!data)
1054
+ data = downData;
1055
+ if (!downData)
1056
+ return;
1057
+ PointerButton.defaultLeft(data);
1058
+ data.multiTouch = downData.multiTouch;
1059
+ this.findPath(data);
1060
+ const upData = Object.assign(Object.assign({}, data), { path: data.path.clone() });
1061
+ data.path.addList(downData.path.list);
1062
+ this.checkPath(data);
1063
+ this.downData = null;
1064
+ this.emit(PointerEvent.BEFORE_UP, data);
1065
+ this.emit(PointerEvent.UP, data);
1066
+ this.touchLeave(data);
1067
+ if (!data.isCancel) {
1068
+ this.tap(data);
1069
+ this.menuTap(data);
1070
+ }
1071
+ this.dragger.dragEnd(data);
1072
+ this.updateCursor(upData);
1073
+ }
1074
+ pointerCancel() {
1075
+ const data = Object.assign({}, this.dragger.dragData);
1076
+ data.isCancel = true;
1077
+ this.pointerUp(data);
1078
+ }
1079
+ multiTouch(data, list) {
1080
+ const { move, angle, scale, center } = MultiTouchHelper.getData(list);
1081
+ this.rotate(getRotateEventData(center, angle, data));
1082
+ this.zoom(getZoomEventData(center, scale, data));
1083
+ this.move(getMoveEventData(center, move, data));
1084
+ }
1085
+ menu(data) {
1086
+ this.findPath(data);
1087
+ this.emit(PointerEvent.MENU, data);
1088
+ }
1089
+ menuTap(data) {
1090
+ if (this.waitMenuTap)
1091
+ this.emit(PointerEvent.MENU_TAP, data);
1092
+ }
1093
+ move(data) {
1094
+ this.transformer.move(data);
1095
+ }
1096
+ zoom(data) {
1097
+ this.transformer.zoom(data);
1098
+ }
1099
+ rotate(data) {
1100
+ this.transformer.rotate(data);
1101
+ }
1102
+ transformEnd() {
1103
+ this.transformer.transformEnd();
1104
+ }
1105
+ keyDown(data) {
1106
+ if (!this.config.keyEvent)
1107
+ return;
1108
+ const { code } = data;
1109
+ if (!this.downKeyMap[code]) {
1110
+ this.downKeyMap[code] = true;
1111
+ Keyboard.setDownCode(code);
1112
+ this.emit(KeyEvent.HOLD, data, this.defaultPath);
1113
+ if (this.moveMode) {
1114
+ this.cancelHover();
1115
+ this.updateCursor();
1116
+ }
1117
+ }
1118
+ this.emit(KeyEvent.DOWN, data, this.defaultPath);
1119
+ }
1120
+ keyUp(data) {
1121
+ if (!this.config.keyEvent)
1122
+ return;
1123
+ const { code } = data;
1124
+ this.downKeyMap[code] = false;
1125
+ Keyboard.setUpCode(code);
1126
+ this.emit(KeyEvent.UP, data, this.defaultPath);
1127
+ if (this.cursor === 'grab')
1128
+ this.updateCursor();
1129
+ }
1130
+ pointerHover(data) {
1131
+ if (this.canHover) {
1132
+ this.pointerOverOrOut(data);
1133
+ this.pointerEnterOrLeave(data);
1134
+ }
1135
+ }
1136
+ pointerOverOrOut(data) {
1137
+ const { path } = data;
1138
+ const { overPath } = this;
1139
+ this.overPath = path;
1140
+ if (overPath) {
1141
+ if (path.indexAt(0) !== overPath.indexAt(0)) {
1142
+ this.emit(PointerEvent.OUT, data, overPath);
1143
+ this.emit(PointerEvent.OVER, data, path);
1144
+ }
1145
+ }
1146
+ else {
1147
+ this.emit(PointerEvent.OVER, data, path);
1148
+ }
1149
+ }
1150
+ pointerEnterOrLeave(data) {
1151
+ let { path } = data;
1152
+ if (this.downData && !this.moveMode) {
1153
+ path = path.clone();
1154
+ this.downData.path.forEach(leaf => path.add(leaf));
1155
+ }
1156
+ const { enterPath } = this;
1157
+ this.enterPath = path;
1158
+ this.emit(PointerEvent.LEAVE, data, enterPath, path);
1159
+ this.emit(PointerEvent.ENTER, data, path, enterPath);
1160
+ }
1161
+ touchLeave(data) {
1162
+ if (data.pointerType === 'touch') {
1163
+ if (this.enterPath) {
1164
+ this.emit(PointerEvent.LEAVE, data);
1165
+ if (this.dragger.dragging)
1166
+ this.emit(DropEvent.LEAVE, data);
1167
+ }
1168
+ }
1169
+ }
1170
+ tap(data) {
1171
+ const { pointer } = this.config;
1172
+ const hasLong = this.longTap(data);
1173
+ if (!pointer.tapMore && hasLong)
1174
+ return;
1175
+ if (!this.waitTap)
1176
+ return;
1177
+ if (pointer.tapMore)
1178
+ this.emitTap(data);
1179
+ const useTime = Date.now() - this.downTime;
1180
+ const hasDouble = [PointerEvent.DOUBLE_TAP, PointerEvent.DOUBLE_CLICK].some(type => pathHasEventType(data.path, type));
1181
+ if (useTime < pointer.tapTime + 50 && hasDouble) {
1182
+ this.tapCount++;
1183
+ if (this.tapCount === 2) {
1184
+ this.tapWaitCancel();
1185
+ this.emitDoubleTap(data);
1186
+ }
1187
+ else {
1188
+ clearTimeout(this.tapTimer);
1189
+ this.tapTimer = setTimeout(() => {
1190
+ if (!pointer.tapMore) {
1191
+ this.tapWaitCancel();
1192
+ this.emitTap(data);
1193
+ }
1194
+ }, pointer.tapTime);
1195
+ }
1196
+ }
1197
+ else {
1198
+ if (!pointer.tapMore) {
1199
+ this.tapWaitCancel();
1200
+ this.emitTap(data);
1201
+ }
1202
+ }
1203
+ }
1204
+ findPath(data, options) {
1205
+ const { hitRadius, through } = this.config.pointer;
1206
+ const { bottomList } = this;
1207
+ const find = this.selector.getByPoint(data, hitRadius, Object.assign({ bottomList, name: data.type }, (options || { through })));
1208
+ if (find.throughPath)
1209
+ data.throughPath = find.throughPath;
1210
+ data.path = find.path;
1211
+ return find.path;
1212
+ }
1213
+ isRootPath(data) {
1214
+ return data && data.path.list[0].isLeafer;
1215
+ }
1216
+ isTreePath(data) {
1217
+ const app = this.target.app;
1218
+ if (!app || !app.isApp)
1219
+ return false;
1220
+ return app.editor && (!data.path.has(app.editor) && data.path.has(app.tree) && !data.target.syncEventer);
1221
+ }
1222
+ checkPath(data, useDefaultPath) {
1223
+ if (useDefaultPath || this.canMove(data))
1224
+ data.path = this.defaultPath;
1225
+ }
1226
+ canMove(data) {
1227
+ return this.moveMode && data && data.path.list.every(item => !item.isOutside);
1228
+ }
1229
+ isDrag(leaf) {
1230
+ return this.dragger.getList().has(leaf);
1231
+ }
1232
+ isPress(leaf) {
1233
+ return this.downData && this.downData.path.has(leaf);
1234
+ }
1235
+ isHover(leaf) {
1236
+ return this.enterPath && this.enterPath.has(leaf);
1237
+ }
1238
+ isFocus(leaf) {
1239
+ return this.focusData === leaf;
1240
+ }
1241
+ cancelHover() {
1242
+ const { hoverData } = this;
1243
+ if (hoverData) {
1244
+ hoverData.path = this.defaultPath;
1245
+ this.pointerHover(hoverData);
1246
+ }
1247
+ }
1248
+ updateDownData(data, options, merge) {
1249
+ const { downData } = this;
1250
+ if (!data && downData)
1251
+ data = downData;
1252
+ if (!data)
1253
+ return;
1254
+ this.findPath(data, options);
1255
+ if (merge && downData)
1256
+ data.path.addList(downData.path.list);
1257
+ this.downData = data;
1258
+ }
1259
+ updateHoverData(data) {
1260
+ if (!data)
1261
+ data = this.hoverData;
1262
+ if (!data)
1263
+ return;
1264
+ this.findPath(data, { exclude: this.dragger.getList(), name: PointerEvent.MOVE });
1265
+ this.hoverData = data;
1266
+ }
1267
+ updateCursor(data) {
1268
+ if (!this.config.cursor || !this.canHover)
1269
+ return;
1270
+ if (!data) {
1271
+ this.updateHoverData();
1272
+ data = this.downData || this.hoverData;
1273
+ }
1274
+ if (this.dragger.moving) {
1275
+ return this.setCursor('grabbing');
1276
+ }
1277
+ else if (this.canMove(data)) {
1278
+ return this.setCursor(this.downData ? 'grabbing' : 'grab');
1279
+ }
1280
+ else if (!data)
1281
+ return;
1282
+ let leaf, cursor;
1283
+ const { path } = data;
1284
+ for (let i = 0, len = path.length; i < len; i++) {
1285
+ leaf = path.list[i];
1286
+ cursor = leaf.syncEventer ? leaf.syncEventer.cursor : leaf.cursor;
1287
+ if (cursor)
1288
+ break;
1289
+ }
1290
+ this.setCursor(cursor);
1291
+ }
1292
+ setCursor(cursor) {
1293
+ this.cursor = cursor;
1294
+ }
1295
+ getLocal(clientPoint, updateClient) {
1296
+ const clientBounds = this.canvas.getClientBounds(updateClient);
1297
+ return { x: clientPoint.clientX - clientBounds.x, y: clientPoint.clientY - clientBounds.y };
1298
+ }
1299
+ emitTap(data) {
1300
+ this.emit(PointerEvent.TAP, data);
1301
+ this.emit(PointerEvent.CLICK, data);
1302
+ }
1303
+ emitDoubleTap(data) {
1304
+ this.emit(PointerEvent.DOUBLE_TAP, data);
1305
+ this.emit(PointerEvent.DOUBLE_CLICK, data);
1306
+ }
1307
+ pointerWaitCancel() {
1308
+ this.tapWaitCancel();
1309
+ this.longPressWaitCancel();
1310
+ }
1311
+ tapWait() {
1312
+ clearTimeout(this.tapTimer);
1313
+ this.waitTap = true;
1314
+ }
1315
+ tapWaitCancel() {
1316
+ clearTimeout(this.tapTimer);
1317
+ this.waitTap = false;
1318
+ this.tapCount = 0;
1319
+ }
1320
+ longPressWait(data) {
1321
+ clearTimeout(this.longPressTimer);
1322
+ this.longPressTimer = setTimeout(() => {
1323
+ this.longPressed = true;
1324
+ this.emit(PointerEvent.LONG_PRESS, data);
1325
+ }, this.config.pointer.longPressTime);
1326
+ }
1327
+ longTap(data) {
1328
+ let hasLong;
1329
+ if (this.longPressed) {
1330
+ this.emit(PointerEvent.LONG_TAP, data);
1331
+ if (pathHasEventType(data.path, PointerEvent.LONG_TAP) || pathHasEventType(data.path, PointerEvent.LONG_PRESS))
1332
+ hasLong = true;
1333
+ }
1334
+ this.longPressWaitCancel();
1335
+ return hasLong;
1336
+ }
1337
+ longPressWaitCancel() {
1338
+ clearTimeout(this.longPressTimer);
1339
+ this.longPressed = false;
1340
+ }
1341
+ __onResize() {
1342
+ this.shrinkCanvasBounds = new Bounds(this.canvas.bounds);
1343
+ this.shrinkCanvasBounds.spread(-2);
1344
+ }
1345
+ __listenEvents() {
1346
+ const { target } = this;
1347
+ this.__eventIds = [target.on_(ResizeEvent.RESIZE, this.__onResize, this)];
1348
+ target.once(LeaferEvent.READY, () => this.__onResize());
1349
+ }
1350
+ __removeListenEvents() {
1351
+ this.target.off_(this.__eventIds);
1352
+ this.__eventIds.length = 0;
1353
+ }
1354
+ emit(type, data, path, excludePath) {
1355
+ if (this.running)
1356
+ emit(type, data, path, excludePath);
1357
+ }
1358
+ destroy() {
1359
+ if (this.__eventIds.length) {
1360
+ this.stop();
1361
+ this.__removeListenEvents();
1362
+ this.dragger.destroy();
1363
+ this.transformer.destroy();
1364
+ this.downData = this.overPath = this.enterPath = null;
1365
+ }
1366
+ }
1367
+ }
1368
+
1369
+ class Cursor {
1370
+ static set(name, value) {
1371
+ this.custom[name] = value;
1372
+ }
1373
+ static get(name) {
1374
+ return this.custom[name];
1375
+ }
1376
+ }
1377
+ Cursor.custom = {};
1378
+
1379
+ class HitCanvasManager extends CanvasManager {
1380
+ constructor() {
1381
+ super(...arguments);
1382
+ this.maxTotal = 1000;
1383
+ this.pathList = new LeafList();
1384
+ this.pixelList = new LeafList();
1385
+ }
1386
+ getPixelType(leaf, config) {
1387
+ this.__autoClear();
1388
+ this.pixelList.add(leaf);
1389
+ return Creator.hitCanvas(config);
1390
+ }
1391
+ getPathType(leaf) {
1392
+ this.__autoClear();
1393
+ this.pathList.add(leaf);
1394
+ return Creator.hitCanvas();
1395
+ }
1396
+ clearImageType() {
1397
+ this.__clearLeafList(this.pixelList);
1398
+ }
1399
+ clearPathType() {
1400
+ this.__clearLeafList(this.pathList);
1401
+ }
1402
+ __clearLeafList(leafList) {
1403
+ if (leafList.length) {
1404
+ leafList.forEach(leaf => {
1405
+ if (leaf.__hitCanvas) {
1406
+ leaf.__hitCanvas.destroy();
1407
+ leaf.__hitCanvas = null;
1408
+ }
1409
+ });
1410
+ leafList.reset();
1411
+ }
1412
+ }
1413
+ __autoClear() {
1414
+ if (this.pathList.length + this.pixelList.length > this.maxTotal)
1415
+ this.clear();
1416
+ }
1417
+ clear() {
1418
+ this.clearPathType();
1419
+ this.clearImageType();
1420
+ }
1421
+ }
1422
+
1423
+ const { toInnerRadiusPointOf, copy, setRadius } = PointHelper;
1424
+ const inner = {};
1425
+ const leaf = Leaf.prototype;
1426
+ leaf.__hitWorld = function (point) {
1427
+ if (!this.__.hitSelf)
1428
+ return false;
1429
+ if (this.__.hitRadius) {
1430
+ copy(inner, point), point = inner;
1431
+ setRadius(point, this.__.hitRadius);
1432
+ }
1433
+ toInnerRadiusPointOf(point, this.__world, inner);
1434
+ const { width, height } = this.__world;
1435
+ const isSmall = width < 10 && height < 10;
1436
+ if (this.__.hitBox || isSmall) {
1437
+ if (BoundsHelper.hitRadiusPoint(this.__layout.boxBounds, inner))
1438
+ return true;
1439
+ if (isSmall)
1440
+ return false;
1441
+ }
1442
+ if (this.__layout.hitCanvasChanged || !this.__hitCanvas) {
1443
+ this.__updateHitCanvas();
1444
+ if (!this.__layout.boundsChanged)
1445
+ this.__layout.hitCanvasChanged = false;
1446
+ }
1447
+ return this.__hit(inner);
1448
+ };
1449
+ leaf.__hitFill = function (inner) { var _a; return (_a = this.__hitCanvas) === null || _a === void 0 ? void 0 : _a.hitFill(inner, this.__.windingRule); };
1450
+ leaf.__hitStroke = function (inner, strokeWidth) { var _a; return (_a = this.__hitCanvas) === null || _a === void 0 ? void 0 : _a.hitStroke(inner, strokeWidth); };
1451
+ leaf.__hitPixel = function (inner) { var _a; return (_a = this.__hitCanvas) === null || _a === void 0 ? void 0 : _a.hitPixel(inner, this.__layout.renderBounds, this.__hitCanvas.hitScale); };
1452
+ leaf.__drawHitPath = function (canvas) { if (canvas)
1453
+ this.__drawRenderPath(canvas); };
1454
+
1455
+ const matrix = new Matrix();
1456
+ const ui$2 = UI.prototype;
1457
+ ui$2.__updateHitCanvas = function () {
1458
+ const data = this.__, { hitCanvasManager } = this.leafer;
1459
+ const isHitPixelFill = (data.__pixelFill || data.__isCanvas) && data.hitFill === 'pixel';
1460
+ const isHitPixelStroke = data.__pixelStroke && data.hitStroke === 'pixel';
1461
+ const isHitPixel = isHitPixelFill || isHitPixelStroke;
1462
+ if (!this.__hitCanvas)
1463
+ this.__hitCanvas = isHitPixel ? hitCanvasManager.getPixelType(this, { contextSettings: { willReadFrequently: true } }) : hitCanvasManager.getPathType(this);
1464
+ const h = this.__hitCanvas;
1465
+ if (isHitPixel) {
1466
+ const { renderBounds } = this.__layout;
1467
+ const size = Platform.image.hitCanvasSize;
1468
+ const scale = h.hitScale = tempBounds.set(0, 0, size, size).getFitMatrix(renderBounds, 0.5).a;
1469
+ const { x, y, width, height } = tempBounds.set(renderBounds).scale(scale);
1470
+ h.resize({ width, height, pixelRatio: 1 });
1471
+ h.clear();
1472
+ ImageManager.patternLocked = true;
1473
+ this.__renderShape(h, { matrix: matrix.setWith(this.__world).scaleWith(1 / scale).invertWith().translate(-x, -y) }, !isHitPixelFill, !isHitPixelStroke);
1474
+ ImageManager.patternLocked = false;
1475
+ h.resetTransform();
1476
+ data.__isHitPixel = true;
1477
+ }
1478
+ else {
1479
+ data.__isHitPixel && (data.__isHitPixel = false);
1480
+ }
1481
+ this.__drawHitPath(h);
1482
+ h.setStrokeOptions(data);
1483
+ };
1484
+ ui$2.__hit = function (inner) {
1485
+ if (Platform.name === 'miniapp')
1486
+ this.__drawHitPath(this.__hitCanvas);
1487
+ const data = this.__;
1488
+ if (data.__isHitPixel && this.__hitPixel(inner))
1489
+ return true;
1490
+ const { hitFill } = data;
1491
+ const needHitFillPath = ((data.fill || data.__isCanvas) && (hitFill === 'path' || (hitFill === 'pixel' && !(data.__pixelFill || data.__isCanvas)))) || hitFill === 'all';
1492
+ if (needHitFillPath && this.__hitFill(inner))
1493
+ return true;
1494
+ const { hitStroke, __strokeWidth } = data;
1495
+ const needHitStrokePath = (data.stroke && (hitStroke === 'path' || (hitStroke === 'pixel' && !data.__pixelStroke))) || hitStroke === 'all';
1496
+ if (!needHitFillPath && !needHitStrokePath)
1497
+ return false;
1498
+ const radiusWidth = inner.radiusX * 2;
1499
+ let hitWidth = radiusWidth;
1500
+ if (needHitStrokePath) {
1501
+ switch (data.strokeAlign) {
1502
+ case 'inside':
1503
+ hitWidth += __strokeWidth * 2;
1504
+ if (!needHitFillPath && this.__hitFill(inner) && this.__hitStroke(inner, hitWidth))
1505
+ return true;
1506
+ hitWidth = radiusWidth;
1507
+ break;
1508
+ case 'center':
1509
+ hitWidth += __strokeWidth;
1510
+ break;
1511
+ case 'outside':
1512
+ hitWidth += __strokeWidth * 2;
1513
+ if (!needHitFillPath) {
1514
+ if (!this.__hitFill(inner) && this.__hitStroke(inner, hitWidth))
1515
+ return true;
1516
+ hitWidth = radiusWidth;
1517
+ }
1518
+ break;
1519
+ }
1520
+ }
1521
+ return hitWidth ? this.__hitStroke(inner, hitWidth) : false;
1522
+ };
1523
+
1524
+ const ui$1 = new UI();
1525
+ const rect = Rect.prototype;
1526
+ rect.__updateHitCanvas = function () {
1527
+ if (this.stroke || this.cornerRadius || ((this.fill || this.__.__isCanvas) && this.hitFill === 'pixel') || this.hitStroke === 'all')
1528
+ ui$1.__updateHitCanvas.call(this);
1529
+ else if (this.__hitCanvas)
1530
+ this.__hitCanvas = null;
1531
+ };
1532
+ rect.__hitFill = function (inner) {
1533
+ return this.__hitCanvas ? ui$1.__hitFill.call(this, inner) : BoundsHelper.hitRadiusPoint(this.__layout.boxBounds, inner);
1534
+ };
1535
+
1536
+ const ui = UI.prototype, group = Group.prototype;
1537
+ ui.find = function (condition, options) {
1538
+ return this.leafer ? this.leafer.selector.getBy(condition, this, false, options) : [];
1539
+ };
1540
+ ui.findOne = function (condition, options) {
1541
+ return this.leafer ? this.leafer.selector.getBy(condition, this, true, options) : null;
1542
+ };
1543
+ group.pick = function (hitPoint, options) {
1544
+ this.__layout.update();
1545
+ if (!options)
1546
+ options = {};
1547
+ return this.leafer ? this.leafer.selector.getByPoint(hitPoint, options.hitRadius || 0, Object.assign(Object.assign({}, options), { target: this })) : null;
1548
+ };
1549
+
1550
+ const canvas = LeaferCanvasBase.prototype;
1551
+ canvas.hitFill = function (point, fillRule) {
1552
+ return fillRule ? this.context.isPointInPath(point.x, point.y, fillRule) : this.context.isPointInPath(point.x, point.y);
1553
+ };
1554
+ canvas.hitStroke = function (point, strokeWidth) {
1555
+ this.strokeWidth = strokeWidth;
1556
+ return this.context.isPointInStroke(point.x, point.y);
1557
+ };
1558
+ canvas.hitPixel = function (radiusPoint, offset, scale = 1) {
1559
+ let { x, y, radiusX, radiusY } = radiusPoint;
1560
+ if (offset)
1561
+ x -= offset.x, y -= offset.y;
1562
+ tempBounds.set(x - radiusX, y - radiusY, radiusX * 2, radiusY * 2).scale(scale).ceil();
1563
+ const { data } = this.context.getImageData(tempBounds.x, tempBounds.y, tempBounds.width || 1, tempBounds.height || 1);
1564
+ for (let i = 0, len = data.length; i < len; i += 4) {
1565
+ if (data[i + 3] > 0)
1566
+ return true;
1567
+ }
1568
+ return data[3] > 0;
1569
+ };
1570
+
1571
+ export { App, Cursor, DragEvent, DropEvent, HitCanvasManager, InteractionBase, InteractionHelper, KeyEvent, Keyboard, LeaferTypeCreator, MoveEvent, MultiTouchHelper, PointerButton, PointerEvent, RotateEvent, SwipeEvent, UIEvent, ZoomEvent, addInteractionWindow };