@leafer-ui/core 1.0.0-rc.2 → 1.0.0-rc.20

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