@eva/plugin-worker 2.0.1-beta.26 → 2.0.1-beta.28

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.
@@ -1,14 +1,35 @@
1
1
  import { Ticker, UPDATE_PRIORITY, Point, warn, ExtensionType, extensions, Container, DOMAdapter, WebWorkerAdapter } from 'pixi.js';
2
2
  import EventEmitter from 'eventemitter3';
3
3
 
4
+ /**
5
+ * 事件时钟类
6
+ *
7
+ * EventsTicker 用于在指针静止时自动触发指针事件,
8
+ * 确保即使指针不移动,移动的对象也能正确触发悬停测试。
9
+ * 这对于实现动态对象的鼠标交互至关重要。
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * EventsTicker.init(eventSystem);
14
+ * EventsTicker.addTickerListener();
15
+ * EventsTicker.pointerMoved(); // 标记指针已移动
16
+ * ```
17
+ *
18
+ * @since 7.2.0
19
+ */
4
20
  class EventsTickerClass {
5
21
  constructor() {
22
+ /** 触发模拟事件的频率(毫秒) */
6
23
  this.interactionFrequency = 10;
7
24
  this._deltaTime = 0;
8
25
  this._didMove = false;
9
26
  this._tickerAdded = false;
10
27
  this._pauseUpdate = true;
11
28
  }
29
+ /**
30
+ * Initializes the event ticker.
31
+ * @param events - The event system.
32
+ */
12
33
  init(events) {
13
34
  this.removeTickerListener();
14
35
  this.events = events;
@@ -18,12 +39,14 @@ class EventsTickerClass {
18
39
  this._tickerAdded = false;
19
40
  this._pauseUpdate = true;
20
41
  }
42
+ /** Whether to pause the update checks or not. */
21
43
  get pauseUpdate() {
22
44
  return this._pauseUpdate;
23
45
  }
24
46
  set pauseUpdate(paused) {
25
47
  this._pauseUpdate = paused;
26
48
  }
49
+ /** Adds the ticker listener. */
27
50
  addTickerListener() {
28
51
  if (this._tickerAdded || !this.domElement) {
29
52
  return;
@@ -31,6 +54,7 @@ class EventsTickerClass {
31
54
  Ticker.system.add(this._tickerUpdate, this, UPDATE_PRIORITY.INTERACTION);
32
55
  this._tickerAdded = true;
33
56
  }
57
+ /** Removes the ticker listener. */
34
58
  removeTickerListener() {
35
59
  if (!this._tickerAdded) {
36
60
  return;
@@ -38,17 +62,21 @@ class EventsTickerClass {
38
62
  Ticker.system.remove(this._tickerUpdate, this);
39
63
  this._tickerAdded = false;
40
64
  }
65
+ /** Sets flag to not fire extra events when the user has already moved there mouse */
41
66
  pointerMoved() {
42
67
  this._didMove = true;
43
68
  }
69
+ /** Updates the state of interactive objects. */
44
70
  _update() {
45
71
  if (!this.domElement || this._pauseUpdate) {
46
72
  return;
47
73
  }
74
+ // if the user move the mouse this check has already been done using the mouse move!
48
75
  if (this._didMove) {
49
76
  this._didMove = false;
50
77
  return;
51
78
  }
79
+ // eslint-disable-next-line dot-notation
52
80
  const rootPointerEvent = this.events['_rootPointerEvent'];
53
81
  if (this.events.supportsTouchEvents && rootPointerEvent.pointerType === 'touch') {
54
82
  return;
@@ -60,6 +88,13 @@ class EventsTickerClass {
60
88
  pointerId: rootPointerEvent.pointerId,
61
89
  }));
62
90
  }
91
+ /**
92
+ * Updates the state of interactive objects if at least {@link interactionFrequency}
93
+ * milliseconds have passed since the last invocation.
94
+ *
95
+ * Invoked by a throttled ticker update from {@link Ticker.system}.
96
+ * @param ticker - The throttled ticker.
97
+ */
63
98
  _tickerUpdate(ticker) {
64
99
  this._deltaTime += ticker.deltaTime;
65
100
  if (this._deltaTime < this.interactionFrequency) {
@@ -71,17 +106,64 @@ class EventsTickerClass {
71
106
  }
72
107
  const EventsTicker = new EventsTickerClass();
73
108
 
109
+ /**
110
+ * 联合事件类
111
+ *
112
+ * FederatedEvent 是一个兼容 DOM 的合成事件实现,
113
+ * 代表原始的 FederatedEvent 或原生 DOM 事件进行传播。
114
+ * 它提供了统一的事件接口,抹平了不同浏览器和设备之间的差异。
115
+ *
116
+ * 主要特性:
117
+ * - 兼容 DOM Event API
118
+ * - 支持事件冒泡和捕获
119
+ * - 提供事件传播控制
120
+ * - 记录事件路径
121
+ *
122
+ * @typeParam N - 持有的原生事件类型
123
+ *
124
+ * @example
125
+ * ```typescript
126
+ * sprite.on('pointerdown', (event: FederatedPointerEvent) => {
127
+ * console.log('Clicked at:', event.global.x, event.global.y);
128
+ * event.stopPropagation(); // 停止事件传播
129
+ * });
130
+ * ```
131
+ */
74
132
  class FederatedEvent {
133
+ /**
134
+ * @param manager - The event boundary which manages this event. Propagation can only occur
135
+ * within the boundary's jurisdiction.
136
+ */
75
137
  constructor(manager) {
138
+ /** 事件是否冒泡(仅在传播前设置有效) */
76
139
  this.bubbles = true;
140
+ /** @deprecated 自 7.0.0 起弃用 */
77
141
  this.cancelBubble = true;
142
+ /**
143
+ * 事件是否可以被取消
144
+ * @readonly
145
+ */
78
146
  this.cancelable = false;
147
+ /**
148
+ * Flag added for compatibility with DOM {@code Event}. It is not used in the Federated Events
149
+ * API.
150
+ * @see https://dom.spec.whatwg.org/#dom-event-composed
151
+ */
79
152
  this.composed = false;
153
+ /** Flags whether the default response of the user agent was prevent through this event. */
80
154
  this.defaultPrevented = false;
155
+ /**
156
+ * The propagation phase.
157
+ * @default {@link FederatedEvent.NONE}
158
+ */
81
159
  this.eventPhase = FederatedEvent.prototype.NONE;
160
+ /** Flags whether propagation was stopped. */
82
161
  this.propagationStopped = false;
162
+ /** Flags whether propagation was immediately stopped. */
83
163
  this.propagationImmediatelyStopped = false;
164
+ /** The coordinates of the event relative to the nearest DOM layer. This is a non-standard property. */
84
165
  this.layer = new Point();
166
+ /** The coordinates of the event relative to the DOM document. This is a non-standard property. */
85
167
  this.page = new Point();
86
168
  this.NONE = 0;
87
169
  this.CAPTURING_PHASE = 1;
@@ -89,147 +171,373 @@ class FederatedEvent {
89
171
  this.BUBBLING_PHASE = 3;
90
172
  this.manager = manager;
91
173
  }
174
+ /** @readonly */
92
175
  get layerX() {
93
176
  return this.layer.x;
94
177
  }
178
+ /** @readonly */
95
179
  get layerY() {
96
180
  return this.layer.y;
97
181
  }
182
+ /** @readonly */
98
183
  get pageX() {
99
184
  return this.page.x;
100
185
  }
186
+ /** @readonly */
101
187
  get pageY() {
102
188
  return this.page.y;
103
189
  }
190
+ /**
191
+ * Fallback for the deprecated @code{InteractionEvent.data}.
192
+ * @deprecated since 7.0.0
193
+ */
104
194
  get data() {
105
195
  return this;
106
196
  }
197
+ /** The propagation path for this event. Alias for {@link EventBoundary.propagationPath}. */
107
198
  composedPath() {
199
+ // Find the propagation path if it isn't cached or if the target has changed since since
200
+ // the last evaluation.
108
201
  if (this.manager && (!this.path || this.path[this.path.length - 1] !== this.target)) {
109
202
  this.path = this.target ? this.manager.propagationPath(this.target) : [];
110
203
  }
111
204
  return this.path;
112
205
  }
206
+ /**
207
+ * Unimplemented method included for implementing the DOM interface {@code Event}. It will throw an {@code Error}.
208
+ * @deprecated
209
+ * @param _type
210
+ * @param _bubbles
211
+ * @param _cancelable
212
+ */
113
213
  initEvent(_type, _bubbles, _cancelable) {
114
214
  throw new Error('initEvent() is a legacy DOM API. It is not implemented in the Federated Events API.');
115
215
  }
216
+ /**
217
+ * Unimplemented method included for implementing the DOM interface {@code UIEvent}. It will throw an {@code Error}.
218
+ * @deprecated
219
+ * @param _typeArg
220
+ * @param _bubblesArg
221
+ * @param _cancelableArg
222
+ * @param _viewArg
223
+ * @param _detailArg
224
+ */
116
225
  initUIEvent(_typeArg, _bubblesArg, _cancelableArg, _viewArg, _detailArg) {
117
226
  throw new Error('initUIEvent() is a legacy DOM API. It is not implemented in the Federated Events API.');
118
227
  }
228
+ /** Prevent default behavior of PixiJS and the user agent. */
119
229
  preventDefault() {
120
230
  if (this.nativeEvent instanceof Event && this.nativeEvent.cancelable) {
121
231
  this.nativeEvent.preventDefault();
122
232
  }
123
233
  this.defaultPrevented = true;
124
234
  }
235
+ /**
236
+ * Stop this event from propagating to any addition listeners, including on the
237
+ * {@link FederatedEventTarget.currentTarget currentTarget} and also the following
238
+ * event targets on the propagation path.
239
+ */
125
240
  stopImmediatePropagation() {
126
241
  this.propagationImmediatelyStopped = true;
127
242
  }
243
+ /**
244
+ * Stop this event from propagating to the next {@link FederatedEventTarget}. The rest of the listeners
245
+ * on the {@link FederatedEventTarget.currentTarget currentTarget} will still be notified.
246
+ */
128
247
  stopPropagation() {
129
248
  this.propagationStopped = true;
130
249
  }
131
250
  }
132
251
 
252
+ /**
253
+ * A {@link FederatedEvent} for mouse events.
254
+ * @memberof events
255
+ */
133
256
  class FederatedMouseEvent extends FederatedEvent {
134
257
  constructor() {
135
258
  super(...arguments);
259
+ /** The coordinates of the mouse event relative to the canvas. */
136
260
  this.client = new Point();
261
+ /** The movement in this pointer relative to the last `mousemove` event. */
137
262
  this.movement = new Point();
263
+ /** The offset of the pointer coordinates w.r.t. target Container in world space. This is not supported at the moment. */
138
264
  this.offset = new Point();
265
+ /** The pointer coordinates in world space. */
139
266
  this.global = new Point();
267
+ /**
268
+ * The pointer coordinates in the renderer's {@link Renderer.screen screen}. This has slightly
269
+ * different semantics than native PointerEvent screenX/screenY.
270
+ */
140
271
  this.screen = new Point();
141
272
  }
273
+ /** @readonly */
142
274
  get clientX() {
143
275
  return this.client.x;
144
276
  }
277
+ /** @readonly */
145
278
  get clientY() {
146
279
  return this.client.y;
147
280
  }
281
+ /**
282
+ * Alias for {@link FederatedMouseEvent.clientX this.clientX}.
283
+ * @readonly
284
+ */
148
285
  get x() {
149
286
  return this.clientX;
150
287
  }
288
+ /**
289
+ * Alias for {@link FederatedMouseEvent.clientY this.clientY}.
290
+ * @readonly
291
+ */
151
292
  get y() {
152
293
  return this.clientY;
153
294
  }
295
+ /** @readonly */
154
296
  get movementX() {
155
297
  return this.movement.x;
156
298
  }
299
+ /** @readonly */
157
300
  get movementY() {
158
301
  return this.movement.y;
159
302
  }
303
+ /** @readonly */
160
304
  get offsetX() {
161
305
  return this.offset.x;
162
306
  }
307
+ /** @readonly */
163
308
  get offsetY() {
164
309
  return this.offset.y;
165
310
  }
311
+ /** @readonly */
166
312
  get globalX() {
167
313
  return this.global.x;
168
314
  }
315
+ /** @readonly */
169
316
  get globalY() {
170
317
  return this.global.y;
171
318
  }
319
+ /**
320
+ * The pointer coordinates in the renderer's screen. Alias for {@code screen.x}.
321
+ * @readonly
322
+ */
172
323
  get screenX() {
173
324
  return this.screen.x;
174
325
  }
326
+ /**
327
+ * The pointer coordinates in the renderer's screen. Alias for {@code screen.y}.
328
+ * @readonly
329
+ */
175
330
  get screenY() {
176
331
  return this.screen.y;
177
332
  }
333
+ /**
334
+ * This will return the local coordinates of the specified container for this InteractionData
335
+ * @param {Container} container - The Container that you would like the local
336
+ * coords off
337
+ * @param {PointData} point - A Point object in which to store the value, optional (otherwise
338
+ * will create a new point)
339
+ * @param {PointData} globalPos - A Point object containing your custom global coords, optional
340
+ * (otherwise will use the current global coords)
341
+ * @returns - A point containing the coordinates of the InteractionData position relative
342
+ * to the Container
343
+ */
178
344
  getLocalPosition(container, point, globalPos) {
179
345
  return container.worldTransform.applyInverse(globalPos || this.global, point);
180
346
  }
347
+ /**
348
+ * Whether the modifier key was pressed when this event natively occurred.
349
+ * @param key - The modifier key.
350
+ */
181
351
  getModifierState(key) {
182
352
  return 'getModifierState' in this.nativeEvent && this.nativeEvent.getModifierState(key);
183
353
  }
354
+ /**
355
+ * Not supported.
356
+ * @param _typeArg
357
+ * @param _canBubbleArg
358
+ * @param _cancelableArg
359
+ * @param _viewArg
360
+ * @param _detailArg
361
+ * @param _screenXArg
362
+ * @param _screenYArg
363
+ * @param _clientXArg
364
+ * @param _clientYArg
365
+ * @param _ctrlKeyArg
366
+ * @param _altKeyArg
367
+ * @param _shiftKeyArg
368
+ * @param _metaKeyArg
369
+ * @param _buttonArg
370
+ * @param _relatedTargetArg
371
+ * @deprecated since 7.0.0
372
+ */
373
+ // eslint-disable-next-line max-params
184
374
  initMouseEvent(_typeArg, _canBubbleArg, _cancelableArg, _viewArg, _detailArg, _screenXArg, _screenYArg, _clientXArg, _clientYArg, _ctrlKeyArg, _altKeyArg, _shiftKeyArg, _metaKeyArg, _buttonArg, _relatedTargetArg) {
185
375
  throw new Error('Method not implemented.');
186
376
  }
187
377
  }
188
378
 
379
+ /**
380
+ * A {@link FederatedEvent} for pointer events.
381
+ * @memberof events
382
+ */
189
383
  class FederatedPointerEvent extends FederatedMouseEvent {
190
384
  constructor() {
191
385
  super(...arguments);
386
+ /**
387
+ * The width of the pointer's contact along the x-axis, measured in CSS pixels.
388
+ * radiusX of TouchEvents will be represented by this value.
389
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/width
390
+ */
192
391
  this.width = 0;
392
+ /**
393
+ * The height of the pointer's contact along the y-axis, measured in CSS pixels.
394
+ * radiusY of TouchEvents will be represented by this value.
395
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/height
396
+ */
193
397
  this.height = 0;
398
+ /**
399
+ * Indicates whether or not the pointer device that created the event is the primary pointer.
400
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent/isPrimary
401
+ */
194
402
  this.isPrimary = false;
195
403
  }
404
+ // Only included for completeness for now
196
405
  getCoalescedEvents() {
197
406
  if (this.type === 'pointermove' || this.type === 'mousemove' || this.type === 'touchmove') {
198
407
  return [this];
199
408
  }
200
409
  return [];
201
410
  }
411
+ // Only included for completeness for now
202
412
  getPredictedEvents() {
203
413
  throw new Error('getPredictedEvents is not supported!');
204
414
  }
205
415
  }
206
416
 
417
+ /**
418
+ * A {@link FederatedEvent} for wheel events.
419
+ * @memberof events
420
+ */
207
421
  class FederatedWheelEvent extends FederatedMouseEvent {
208
422
  constructor() {
209
423
  super(...arguments);
424
+ /** Units specified in pixels. */
210
425
  this.DOM_DELTA_PIXEL = 0;
426
+ /** Units specified in lines. */
211
427
  this.DOM_DELTA_LINE = 1;
428
+ /** Units specified in pages. */
212
429
  this.DOM_DELTA_PAGE = 2;
213
430
  }
214
431
  }
432
+ /** Units specified in pixels. */
215
433
  FederatedWheelEvent.DOM_DELTA_PIXEL = 0;
434
+ /** Units specified in lines. */
216
435
  FederatedWheelEvent.DOM_DELTA_LINE = 1;
436
+ /** Units specified in pages. */
217
437
  FederatedWheelEvent.DOM_DELTA_PAGE = 2;
218
438
 
439
+ // The maximum iterations used in propagation. This prevent infinite loops.
219
440
  const PROPAGATION_LIMIT = 2048;
220
441
  const tempHitLocation = new Point();
221
442
  const tempLocalMapping = new Point();
443
+ /**
444
+ * Event boundaries are "barriers" where events coming from an upstream scene are modified before downstream propagation.
445
+ *
446
+ * ## Root event boundary
447
+ *
448
+ * The {@link EventSystem#rootBoundary rootBoundary} handles events coming from the &lt;canvas /&gt;.
449
+ * {@link EventSystem} handles the normalization from native {@link https://dom.spec.whatwg.org/#event Events}
450
+ * into {@link FederatedEvent FederatedEvents}. The rootBoundary then does the hit-testing and event dispatch
451
+ * for the upstream normalized event.
452
+ *
453
+ * ## Additional event boundaries
454
+ *
455
+ * An additional event boundary may be desired within an application's scene graph. For example, if a portion of the scene is
456
+ * is flat with many children at one level - a spatial hash maybe needed to accelerate hit testing. In this scenario, the
457
+ * container can be detached from the scene and glued using a custom event boundary.
458
+ *
459
+ * ```ts
460
+ * import { Container } from 'pixi.js';
461
+ * import { EventBoundary } from 'pixi.js';
462
+ * import { SpatialHash } from 'pixi-spatial-hash';
463
+ *
464
+ * class HashedHitTestingEventBoundary
465
+ * {
466
+ * private spatialHash: SpatialHash;
467
+ *
468
+ * constructor(scene: Container, spatialHash: SpatialHash)
469
+ * {
470
+ * super(scene);
471
+ * this.spatialHash = spatialHash;
472
+ * }
473
+ *
474
+ * hitTestRecursive(...)
475
+ * {
476
+ * // TODO: If target === this.rootTarget, then use spatial hash to get a
477
+ * // list of possible children that match the given (x,y) coordinates.
478
+ * }
479
+ * }
480
+ *
481
+ * class VastScene extends Container
482
+ * {
483
+ * protected eventBoundary: EventBoundary;
484
+ * protected scene: Container;
485
+ * protected spatialHash: SpatialHash;
486
+ *
487
+ * constructor()
488
+ * {
489
+ * this.scene = new Container();
490
+ * this.spatialHash = new SpatialHash();
491
+ * this.eventBoundary = new HashedHitTestingEventBoundary(this.scene, this.spatialHash);
492
+ *
493
+ * // Populate this.scene with a ton of children, while updating this.spatialHash
494
+ * }
495
+ * }
496
+ * ```
497
+ * @memberof events
498
+ */
222
499
  class EventBoundary {
500
+ /**
501
+ * @param rootTarget - The holder of the event boundary.
502
+ */
223
503
  constructor(rootTarget) {
504
+ /**
505
+ * Emits events after they were dispatched into the scene graph.
506
+ *
507
+ * This can be used for global events listening, regardless of the scene graph being used. It should
508
+ * not be used by interactive libraries for normal use.
509
+ *
510
+ * Special events that do not bubble all the way to the root target are not emitted from here,
511
+ * e.g. pointerenter, pointerleave, click.
512
+ */
224
513
  this.dispatch = new EventEmitter();
514
+ /**
515
+ * This flag would emit `pointermove`, `touchmove`, and `mousemove` events on all Containers.
516
+ *
517
+ * The `moveOnAll` semantics mirror those of earlier versions of PixiJS. This was disabled in favor of
518
+ * the Pointer Event API's approach.
519
+ */
225
520
  this.moveOnAll = false;
521
+ /** Enables the global move events. `globalpointermove`, `globaltouchmove`, and `globalmousemove` */
226
522
  this.enableGlobalMoveEvents = true;
523
+ /**
524
+ * State object for mapping methods.
525
+ * @see EventBoundary#trackingData
526
+ */
227
527
  this.mappingState = {
228
528
  trackingData: {},
229
529
  };
530
+ /**
531
+ * The event pool maps event constructors to an free pool of instances of those specific events.
532
+ * @see EventBoundary#allocateEvent
533
+ * @see EventBoundary#freeEvent
534
+ */
230
535
  this.eventPool = new Map();
536
+ /** Every interactive element gathered from the scene. Only used in `pointermove` */
231
537
  this._allInteractiveElements = [];
538
+ /** Every element that passed the hit test. Only used in `pointermove` */
232
539
  this._hitElements = [];
540
+ /** Whether or not to collect all the interactive elements from the scene. Enabled in `pointermove` */
233
541
  this._isPointerMoveEvent = false;
234
542
  this.rootTarget = rootTarget;
235
543
  this.hitPruneFn = this.hitPruneFn.bind(this);
@@ -251,6 +559,18 @@ class EventBoundary {
251
559
  this.addEventMapping('pointerupoutside', this.mapPointerUpOutside);
252
560
  this.addEventMapping('wheel', this.mapWheel);
253
561
  }
562
+ /**
563
+ * Adds an event mapping for the event `type` handled by `fn`.
564
+ *
565
+ * Event mappings can be used to implement additional or custom events. They take an event
566
+ * coming from the upstream scene (or directly from the {@link EventSystem}) and dispatch new downstream events
567
+ * generally trickling down and bubbling up to {@link EventBoundary.rootTarget this.rootTarget}.
568
+ *
569
+ * To modify the semantics of existing events, the built-in mapping methods of EventBoundary should be overridden
570
+ * instead.
571
+ * @param type - The type of upstream event to map.
572
+ * @param fn - The mapping method. The context of this function must be bound manually, if desired.
573
+ */
254
574
  addEventMapping(type, fn) {
255
575
  if (!this.mappingTable[type]) {
256
576
  this.mappingTable[type] = [];
@@ -261,12 +581,21 @@ class EventBoundary {
261
581
  });
262
582
  this.mappingTable[type].sort((a, b) => a.priority - b.priority);
263
583
  }
584
+ /**
585
+ * Dispatches the given event
586
+ * @param e - The event to dispatch.
587
+ * @param type - The type of event to dispatch. Defaults to `e.type`.
588
+ */
264
589
  dispatchEvent(e, type) {
265
590
  e.propagationStopped = false;
266
591
  e.propagationImmediatelyStopped = false;
267
592
  this.propagate(e, type);
268
593
  this.dispatch.emit(type || e.type, e);
269
594
  }
595
+ /**
596
+ * Maps the given upstream event through the event boundary and propagates it downstream.
597
+ * @param e - The event to map.
598
+ */
270
599
  mapEvent(e) {
271
600
  if (!this.rootTarget) {
272
601
  return;
@@ -278,21 +607,39 @@ class EventBoundary {
278
607
  }
279
608
  }
280
609
  else {
610
+ // #if _DEBUG
281
611
  warn(`[EventBoundary]: Event mapping not defined for ${e.type}`);
612
+ // #endif
282
613
  }
283
614
  }
615
+ /**
616
+ * Finds the Container that is the target of a event at the given coordinates.
617
+ *
618
+ * The passed (x,y) coordinates are in the world space above this event boundary.
619
+ * @param x - The x coordinate of the event.
620
+ * @param y - The y coordinate of the event.
621
+ */
284
622
  hitTest(x, y) {
285
623
  EventsTicker.pauseUpdate = true;
624
+ // if we are using global move events, we need to hit test the whole scene graph
286
625
  const useMove = this._isPointerMoveEvent && this.enableGlobalMoveEvents;
287
626
  const fn = useMove ? 'hitTestMoveRecursive' : 'hitTestRecursive';
288
627
  const invertedPath = this[fn](this.rootTarget, this.rootTarget.eventMode, tempHitLocation.set(x, y), this.hitTestFn, this.hitPruneFn);
289
628
  return invertedPath && invertedPath[0];
290
629
  }
630
+ /**
631
+ * Propagate the passed event from from {@link EventBoundary.rootTarget this.rootTarget} to its
632
+ * target {@code e.target}.
633
+ * @param e - The event to propagate.
634
+ * @param type - The type of event to propagate. Defaults to `e.type`.
635
+ */
291
636
  propagate(e, type) {
292
637
  if (!e.target) {
638
+ // This usually occurs when the scene graph is not interactive.
293
639
  return;
294
640
  }
295
641
  const composedPath = e.composedPath();
642
+ // Capturing phase
296
643
  e.eventPhase = e.CAPTURING_PHASE;
297
644
  for (let i = 0, j = composedPath.length - 1; i < j; i++) {
298
645
  e.currentTarget = composedPath[i];
@@ -300,11 +647,13 @@ class EventBoundary {
300
647
  if (e.propagationStopped || e.propagationImmediatelyStopped)
301
648
  return;
302
649
  }
650
+ // At target phase
303
651
  e.eventPhase = e.AT_TARGET;
304
652
  e.currentTarget = e.target;
305
653
  this.notifyTarget(e, type);
306
654
  if (e.propagationStopped || e.propagationImmediatelyStopped)
307
655
  return;
656
+ // Bubbling phase
308
657
  e.eventPhase = e.BUBBLING_PHASE;
309
658
  for (let i = composedPath.length - 2; i >= 0; i--) {
310
659
  e.currentTarget = composedPath[i];
@@ -313,11 +662,21 @@ class EventBoundary {
313
662
  return;
314
663
  }
315
664
  }
665
+ /**
666
+ * Emits the event {@code e} to all interactive containers. The event is propagated in the bubbling phase always.
667
+ *
668
+ * This is used in the `globalpointermove` event.
669
+ * @param e - The emitted event.
670
+ * @param type - The listeners to notify.
671
+ * @param targets - The targets to notify.
672
+ */
316
673
  all(e, type, targets = this._allInteractiveElements) {
317
674
  if (targets.length === 0)
318
675
  return;
319
676
  e.eventPhase = e.BUBBLING_PHASE;
320
677
  const events = Array.isArray(type) ? type : [type];
678
+ // loop through all interactive elements and notify them of the event
679
+ // loop through targets backwards
321
680
  for (let i = targets.length - 1; i >= 0; i--) {
322
681
  events.forEach(event => {
323
682
  e.currentTarget = targets[i];
@@ -325,6 +684,11 @@ class EventBoundary {
325
684
  });
326
685
  }
327
686
  }
687
+ /**
688
+ * Finds the propagation path from {@link EventBoundary.rootTarget rootTarget} to the passed
689
+ * {@code target}. The last element in the path is {@code target}.
690
+ * @param target - The target to find the propagation path to.
691
+ */
328
692
  propagationPath(target) {
329
693
  const propagationPath = [target];
330
694
  for (let i = 0; i < PROPAGATION_LIMIT && target !== this.rootTarget && target.parent; i++) {
@@ -339,6 +703,7 @@ class EventBoundary {
339
703
  }
340
704
  hitTestMoveRecursive(currentTarget, eventMode, location, testFn, pruneFn, ignore = false) {
341
705
  let shouldReturn = false;
706
+ // only bail out early if it is not interactive
342
707
  if (this._interactivePrune(currentTarget))
343
708
  return null;
344
709
  if (currentTarget.eventMode === 'dynamic' || eventMode === 'dynamic') {
@@ -350,15 +715,21 @@ class EventBoundary {
350
715
  const child = children[i];
351
716
  const nestedHit = this.hitTestMoveRecursive(child, this._isInteractive(eventMode) ? eventMode : child.eventMode, location, testFn, pruneFn, ignore || pruneFn(currentTarget, location));
352
717
  if (nestedHit) {
718
+ // Its a good idea to check if a child has lost its parent.
719
+ // this means it has been removed whilst looping so its best
353
720
  if (nestedHit.length > 0 && !nestedHit[nestedHit.length - 1].parent) {
354
721
  continue;
355
722
  }
723
+ // Only add the current hit-test target to the hit-test chain if the chain
724
+ // has already started (i.e. the event target has been found) or if the current
725
+ // target is interactive (i.e. it becomes the event target).
356
726
  const isInteractive = currentTarget.isInteractive();
357
727
  if (nestedHit.length > 0 || isInteractive) {
358
728
  if (isInteractive)
359
729
  this._allInteractiveElements.push(currentTarget);
360
730
  nestedHit.push(currentTarget);
361
731
  }
732
+ // store all hit elements to be returned once we have traversed the whole tree
362
733
  if (this._hitElements.length === 0)
363
734
  this._hitElements = nestedHit;
364
735
  shouldReturn = true;
@@ -369,22 +740,43 @@ class EventBoundary {
369
740
  const isInteractiveTarget = currentTarget.isInteractive();
370
741
  if (isInteractiveTarget && isInteractiveTarget)
371
742
  this._allInteractiveElements.push(currentTarget);
743
+ // we don't carry on hit testing something once we have found a hit,
744
+ // now only care about gathering the interactive elements
372
745
  if (ignore || this._hitElements.length > 0)
373
746
  return null;
374
747
  if (shouldReturn)
375
748
  return this._hitElements;
749
+ // Finally, hit test this Container itself.
376
750
  if (isInteractiveMode && !pruneFn(currentTarget, location) && testFn(currentTarget, location)) {
751
+ // The current hit-test target is the event's target only if it is interactive. Otherwise,
752
+ // the first interactive ancestor will be the event's target.
377
753
  return isInteractiveTarget ? [currentTarget] : [];
378
754
  }
379
755
  return null;
380
756
  }
757
+ /**
758
+ * Recursive implementation for {@link EventBoundary.hitTest hitTest}.
759
+ * @param currentTarget - The Container that is to be hit tested.
760
+ * @param eventMode - The event mode for the `currentTarget` or one of its parents.
761
+ * @param location - The location that is being tested for overlap.
762
+ * @param testFn - Callback that determines whether the target passes hit testing. This callback
763
+ * can assume that `pruneFn` failed to prune the container.
764
+ * @param pruneFn - Callback that determiness whether the target and all of its children
765
+ * cannot pass the hit test. It is used as a preliminary optimization to prune entire subtrees
766
+ * of the scene graph.
767
+ * @returns An array holding the hit testing target and all its ancestors in order. The first element
768
+ * is the target itself and the last is {@link EventBoundary.rootTarget rootTarget}. This is the opposite
769
+ * order w.r.t. the propagation path. If no hit testing target is found, null is returned.
770
+ */
381
771
  hitTestRecursive(currentTarget, eventMode, location, testFn, pruneFn) {
772
+ // Attempt to prune this Container and its subtree as an optimization.
382
773
  if (this._interactivePrune(currentTarget) || pruneFn(currentTarget, location)) {
383
774
  return null;
384
775
  }
385
776
  if (currentTarget.eventMode === 'dynamic' || eventMode === 'dynamic') {
386
777
  EventsTicker.pauseUpdate = false;
387
778
  }
779
+ // Find a child that passes the hit testing and return one, if any.
388
780
  if (currentTarget.interactiveChildren && currentTarget.children) {
389
781
  const children = currentTarget.children;
390
782
  const relativeLocation = location;
@@ -392,9 +784,14 @@ class EventBoundary {
392
784
  const child = children[i];
393
785
  const nestedHit = this.hitTestRecursive(child, this._isInteractive(eventMode) ? eventMode : child.eventMode, relativeLocation, testFn, pruneFn);
394
786
  if (nestedHit) {
787
+ // Its a good idea to check if a child has lost its parent.
788
+ // this means it has been removed whilst looping so its best
395
789
  if (nestedHit.length > 0 && !nestedHit[nestedHit.length - 1].parent) {
396
790
  continue;
397
791
  }
792
+ // Only add the current hit-test target to the hit-test chain if the chain
793
+ // has already started (i.e. the event target has been found) or if the current
794
+ // target is interactive (i.e. it becomes the event target).
398
795
  const isInteractive = currentTarget.isInteractive();
399
796
  if (nestedHit.length > 0 || isInteractive)
400
797
  nestedHit.push(currentTarget);
@@ -404,7 +801,10 @@ class EventBoundary {
404
801
  }
405
802
  const isInteractiveMode = this._isInteractive(eventMode);
406
803
  const isInteractiveTarget = currentTarget.isInteractive();
804
+ // Finally, hit test this Container itself.
407
805
  if (isInteractiveMode && testFn(currentTarget, location)) {
806
+ // The current hit-test target is the event's target only if it is interactive. Otherwise,
807
+ // the first interactive ancestor will be the event's target.
408
808
  return isInteractiveTarget ? [currentTarget] : [];
409
809
  }
410
810
  return null;
@@ -413,17 +813,28 @@ class EventBoundary {
413
813
  return int === 'static' || int === 'dynamic';
414
814
  }
415
815
  _interactivePrune(container) {
816
+ // If container is a mask, invisible, or not renderable then it cannot be hit directly.
416
817
  if (!container || !container.visible || !container.renderable || !container.measurable) {
417
818
  return true;
418
819
  }
820
+ // If this Container is none then it cannot be hit by anything.
419
821
  if (container.eventMode === 'none') {
420
822
  return true;
421
823
  }
824
+ // If this Container is passive and it has no interactive children then it cannot be hit
422
825
  if (container.eventMode === 'passive' && !container.interactiveChildren) {
423
826
  return true;
424
827
  }
425
828
  return false;
426
829
  }
830
+ /**
831
+ * Checks whether the container or any of its children cannot pass the hit test at all.
832
+ *
833
+ * {@link EventBoundary}'s implementation uses the {@link Container.hitArea hitArea}
834
+ * and {@link Container._maskEffect} for pruning.
835
+ * @param container - The container to prune.
836
+ * @param location - The location to test for overlap.
837
+ */
427
838
  hitPruneFn(container, location) {
428
839
  if (container.hitArea) {
429
840
  container.worldTransform.applyInverse(location, tempLocalMapping);
@@ -444,8 +855,15 @@ class EventBoundary {
444
855
  }
445
856
  return false;
446
857
  }
858
+ /**
859
+ * Checks whether the container passes hit testing for the given location.
860
+ * @param container - The container to test.
861
+ * @param location - The location to test for overlap.
862
+ * @returns - Whether `container` passes hit testing for `location`.
863
+ */
447
864
  hitTestFn(container, location) {
448
865
  var _a;
866
+ // If the container failed pruning with a hitArea, then it must pass it.
449
867
  if (container.hitArea) {
450
868
  return true;
451
869
  }
@@ -453,14 +871,24 @@ class EventBoundary {
453
871
  container.worldTransform.applyInverse(location, tempLocalMapping);
454
872
  return container.containsPoint(tempLocalMapping);
455
873
  }
874
+ // TODO: Should we hit test based on bounds?
456
875
  return false;
457
876
  }
877
+ /**
878
+ * Notify all the listeners to the event's `currentTarget`.
879
+ *
880
+ * If the `currentTarget` contains the property `on<type>`, then it is called here,
881
+ * simulating the behavior from version 6.x and prior.
882
+ * @param e - The event passed to the target.
883
+ * @param type - The type of event to notify. Defaults to `e.type`.
884
+ */
458
885
  notifyTarget(e, type) {
459
886
  var _a;
460
887
  if (!e.currentTarget.isInteractive()) {
461
888
  return;
462
889
  }
463
890
  type = type !== null && type !== void 0 ? type : e.type;
891
+ // call the `on${type}` for the current target if it exists
464
892
  const handlerKey = `on${type}`;
465
893
  (_a = e.currentTarget[handlerKey]) === null || _a === void 0 ? void 0 : _a(e);
466
894
  const key = e.eventPhase === e.CAPTURING_PHASE || e.eventPhase === e.AT_TARGET ? `${type}capture` : type;
@@ -469,9 +897,17 @@ class EventBoundary {
469
897
  this._notifyListeners(e, type);
470
898
  }
471
899
  }
900
+ /**
901
+ * Maps the upstream `pointerdown` events to a downstream `pointerdown` event.
902
+ *
903
+ * `touchstart`, `rightdown`, `mousedown` events are also dispatched for specific pointer types.
904
+ * @param from - The upstream `pointerdown` event.
905
+ */
472
906
  mapPointerDown(from) {
473
907
  if (!(from instanceof FederatedPointerEvent)) {
908
+ // #if _DEBUG
474
909
  warn('EventBoundary cannot map a non-pointer event as a pointer event');
910
+ // #endif
475
911
  return;
476
912
  }
477
913
  const e = this.createPointerEvent(from);
@@ -487,10 +923,19 @@ class EventBoundary {
487
923
  trackingData.pressTargetsByButton[from.button] = e.composedPath();
488
924
  this.freeEvent(e);
489
925
  }
926
+ /**
927
+ * Maps the upstream `pointermove` to downstream `pointerout`, `pointerover`, and `pointermove` events, in that order.
928
+ *
929
+ * The tracking data for the specific pointer has an updated `overTarget`. `mouseout`, `mouseover`,
930
+ * `mousemove`, and `touchmove` events are fired as well for specific pointer types.
931
+ * @param from - The upstream `pointermove` event.
932
+ */
490
933
  mapPointerMove(from) {
491
934
  var _a, _b, _c;
492
935
  if (!(from instanceof FederatedPointerEvent)) {
936
+ // #if _DEBUG
493
937
  warn('EventBoundary cannot map a non-pointer event as a pointer event');
938
+ // #endif
494
939
  return;
495
940
  }
496
941
  this._allInteractiveElements.length = 0;
@@ -501,12 +946,16 @@ class EventBoundary {
501
946
  const isMouse = e.pointerType === 'mouse' || e.pointerType === 'pen';
502
947
  const trackingData = this.trackingData(from.pointerId);
503
948
  const outTarget = this.findMountedTarget(trackingData.overTargets);
949
+ // First pointerout/pointerleave
504
950
  if (((_a = trackingData.overTargets) === null || _a === void 0 ? void 0 : _a.length) > 0 && outTarget !== e.target) {
951
+ // pointerout always occurs on the overTarget when the pointer hovers over another element.
505
952
  const outType = from.type === 'mousemove' ? 'mouseout' : 'pointerout';
506
953
  const outEvent = this.createPointerEvent(from, outType, outTarget);
507
954
  this.dispatchEvent(outEvent, 'pointerout');
508
955
  if (isMouse)
509
956
  this.dispatchEvent(outEvent, 'mouseout');
957
+ // If the pointer exits overTarget and its descendants, then a pointerleave event is also fired. This event
958
+ // is dispatched to all ancestors that no longer capture the pointer.
510
959
  if (!e.composedPath().includes(outTarget)) {
511
960
  const leaveEvent = this.createPointerEvent(from, 'pointerleave', outTarget);
512
961
  leaveEvent.eventPhase = leaveEvent.AT_TARGET;
@@ -521,18 +970,23 @@ class EventBoundary {
521
970
  }
522
971
  this.freeEvent(outEvent);
523
972
  }
973
+ // Then pointerover
524
974
  if (outTarget !== e.target) {
975
+ // pointerover always occurs on the new overTarget
525
976
  const overType = from.type === 'mousemove' ? 'mouseover' : 'pointerover';
526
- const overEvent = this.clonePointerEvent(e, overType);
977
+ const overEvent = this.clonePointerEvent(e, overType); // clone faster
527
978
  this.dispatchEvent(overEvent, 'pointerover');
528
979
  if (isMouse)
529
980
  this.dispatchEvent(overEvent, 'mouseover');
981
+ // Probe whether the newly hovered Container is an ancestor of the original overTarget.
530
982
  let overTargetAncestor = outTarget === null || outTarget === void 0 ? void 0 : outTarget.parent;
531
983
  while (overTargetAncestor && overTargetAncestor !== this.rootTarget.parent) {
532
984
  if (overTargetAncestor === e.target)
533
985
  break;
534
986
  overTargetAncestor = overTargetAncestor.parent;
535
987
  }
988
+ // The pointer has entered a non-ancestor of the original overTarget. This means we need a pointerentered
989
+ // event.
536
990
  const didPointerEnter = !overTargetAncestor || overTargetAncestor === this.rootTarget.parent;
537
991
  if (didPointerEnter) {
538
992
  const enterEvent = this.clonePointerEvent(e, 'pointerenter');
@@ -552,6 +1006,7 @@ class EventBoundary {
552
1006
  const allowGlobalPointerEvents = (_b = this.enableGlobalMoveEvents) !== null && _b !== void 0 ? _b : true;
553
1007
  this.moveOnAll ? allMethods.push('pointermove') : this.dispatchEvent(e, 'pointermove');
554
1008
  allowGlobalPointerEvents && allMethods.push('globalpointermove');
1009
+ // Then pointermove
555
1010
  if (e.pointerType === 'touch') {
556
1011
  this.moveOnAll ? allMethods.splice(1, 0, 'touchmove') : this.dispatchEvent(e, 'touchmove');
557
1012
  allowGlobalPointerEvents && allMethods.push('globaltouchmove');
@@ -569,10 +1024,18 @@ class EventBoundary {
569
1024
  trackingData.overTargets = e.composedPath();
570
1025
  this.freeEvent(e);
571
1026
  }
1027
+ /**
1028
+ * Maps the upstream `pointerover` to downstream `pointerover` and `pointerenter` events, in that order.
1029
+ *
1030
+ * The tracking data for the specific pointer gets a new `overTarget`.
1031
+ * @param from - The upstream `pointerover` event.
1032
+ */
572
1033
  mapPointerOver(from) {
573
1034
  var _a;
574
1035
  if (!(from instanceof FederatedPointerEvent)) {
1036
+ // #if _DEBUG
575
1037
  warn('EventBoundary cannot map a non-pointer event as a pointer event');
1038
+ // #endif
576
1039
  return;
577
1040
  }
578
1041
  const trackingData = this.trackingData(from.pointerId);
@@ -583,6 +1046,7 @@ class EventBoundary {
583
1046
  this.dispatchEvent(e, 'mouseover');
584
1047
  if (e.pointerType === 'mouse')
585
1048
  this.cursor = (_a = e.target) === null || _a === void 0 ? void 0 : _a.cursor;
1049
+ // pointerenter events must be fired since the pointer entered from upstream.
586
1050
  const enterEvent = this.clonePointerEvent(e, 'pointerenter');
587
1051
  enterEvent.eventPhase = enterEvent.AT_TARGET;
588
1052
  while (enterEvent.target && enterEvent.target !== this.rootTarget.parent) {
@@ -596,19 +1060,30 @@ class EventBoundary {
596
1060
  this.freeEvent(e);
597
1061
  this.freeEvent(enterEvent);
598
1062
  }
1063
+ /**
1064
+ * Maps the upstream `pointerout` to downstream `pointerout`, `pointerleave` events, in that order.
1065
+ *
1066
+ * The tracking data for the specific pointer is cleared of a `overTarget`.
1067
+ * @param from - The upstream `pointerout` event.
1068
+ */
599
1069
  mapPointerOut(from) {
600
1070
  if (!(from instanceof FederatedPointerEvent)) {
1071
+ // #if _DEBUG
601
1072
  warn('EventBoundary cannot map a non-pointer event as a pointer event');
1073
+ // #endif
602
1074
  return;
603
1075
  }
604
1076
  const trackingData = this.trackingData(from.pointerId);
605
1077
  if (trackingData.overTargets) {
606
1078
  const isMouse = from.pointerType === 'mouse' || from.pointerType === 'pen';
607
1079
  const outTarget = this.findMountedTarget(trackingData.overTargets);
1080
+ // pointerout first
608
1081
  const outEvent = this.createPointerEvent(from, 'pointerout', outTarget);
609
1082
  this.dispatchEvent(outEvent);
610
1083
  if (isMouse)
611
1084
  this.dispatchEvent(outEvent, 'mouseout');
1085
+ // pointerleave(s) are also dispatched b/c the pointer must've left rootTarget and its descendants to
1086
+ // get an upstream pointerout event (upstream events do not know rootTarget has descendants).
612
1087
  const leaveEvent = this.createPointerEvent(from, 'pointerleave', outTarget);
613
1088
  leaveEvent.eventPhase = leaveEvent.AT_TARGET;
614
1089
  while (leaveEvent.target && leaveEvent.target !== this.rootTarget.parent) {
@@ -624,9 +1099,21 @@ class EventBoundary {
624
1099
  }
625
1100
  this.cursor = null;
626
1101
  }
1102
+ /**
1103
+ * Maps the upstream `pointerup` event to downstream `pointerup`, `pointerupoutside`,
1104
+ * and `click`/`rightclick`/`pointertap` events, in that order.
1105
+ *
1106
+ * The `pointerupoutside` event bubbles from the original `pointerdown` target to the most specific
1107
+ * ancestor of the `pointerdown` and `pointerup` targets, which is also the `click` event's target. `touchend`,
1108
+ * `rightup`, `mouseup`, `touchendoutside`, `rightupoutside`, `mouseupoutside`, and `tap` are fired as well for
1109
+ * specific pointer types.
1110
+ * @param from - The upstream `pointerup` event.
1111
+ */
627
1112
  mapPointerUp(from) {
628
1113
  if (!(from instanceof FederatedPointerEvent)) {
1114
+ // #if _DEBUG
629
1115
  warn('EventBoundary cannot map a non-pointer event as a pointer event');
1116
+ // #endif
630
1117
  return;
631
1118
  }
632
1119
  const now = performance.now();
@@ -642,6 +1129,8 @@ class EventBoundary {
642
1129
  const trackingData = this.trackingData(from.pointerId);
643
1130
  const pressTarget = this.findMountedTarget(trackingData.pressTargetsByButton[from.button]);
644
1131
  let clickTarget = pressTarget;
1132
+ // pointerupoutside only bubbles. It only bubbles upto the parent that doesn't contain
1133
+ // the pointerup location.
645
1134
  if (pressTarget && !e.composedPath().includes(pressTarget)) {
646
1135
  let currentTarget = pressTarget;
647
1136
  while (currentTarget && !e.composedPath().includes(currentTarget)) {
@@ -657,8 +1146,11 @@ class EventBoundary {
657
1146
  currentTarget = currentTarget.parent;
658
1147
  }
659
1148
  delete trackingData.pressTargetsByButton[from.button];
1149
+ // currentTarget is the most specific ancestor holding both the pointerdown and pointerup
1150
+ // targets. That is - it's our click target!
660
1151
  clickTarget = currentTarget;
661
1152
  }
1153
+ // click!
662
1154
  if (clickTarget) {
663
1155
  const clickEvent = this.clonePointerEvent(e, 'click');
664
1156
  clickEvent.target = clickTarget;
@@ -692,9 +1184,22 @@ class EventBoundary {
692
1184
  }
693
1185
  this.freeEvent(e);
694
1186
  }
1187
+ /**
1188
+ * Maps the upstream `pointerupoutside` event to a downstream `pointerupoutside` event, bubbling from the original
1189
+ * `pointerdown` target to `rootTarget`.
1190
+ *
1191
+ * (The most specific ancestor of the `pointerdown` event and the `pointerup` event must the
1192
+ * `{@link EventBoundary}'s root because the `pointerup` event occurred outside of the boundary.)
1193
+ *
1194
+ * `touchendoutside`, `mouseupoutside`, and `rightupoutside` events are fired as well for specific pointer
1195
+ * types. The tracking data for the specific pointer is cleared of a `pressTarget`.
1196
+ * @param from - The upstream `pointerupoutside` event.
1197
+ */
695
1198
  mapPointerUpOutside(from) {
696
1199
  if (!(from instanceof FederatedPointerEvent)) {
1200
+ // #if _DEBUG
697
1201
  warn('EventBoundary cannot map a non-pointer event as a pointer event');
1202
+ // #endif
698
1203
  return;
699
1204
  }
700
1205
  const trackingData = this.trackingData(from.pointerId);
@@ -717,21 +1222,37 @@ class EventBoundary {
717
1222
  }
718
1223
  this.freeEvent(e);
719
1224
  }
1225
+ /**
1226
+ * Maps the upstream `wheel` event to a downstream `wheel` event.
1227
+ * @param from - The upstream `wheel` event.
1228
+ */
720
1229
  mapWheel(from) {
721
1230
  if (!(from instanceof FederatedWheelEvent)) {
1231
+ // #if _DEBUG
722
1232
  warn('EventBoundary cannot map a non-wheel event as a wheel event');
1233
+ // #endif
723
1234
  return;
724
1235
  }
725
1236
  const wheelEvent = this.createWheelEvent(from);
726
1237
  this.dispatchEvent(wheelEvent);
727
1238
  this.freeEvent(wheelEvent);
728
1239
  }
1240
+ /**
1241
+ * Finds the most specific event-target in the given propagation path that is still mounted in the scene graph.
1242
+ *
1243
+ * This is used to find the correct `pointerup` and `pointerout` target in the case that the original `pointerdown`
1244
+ * or `pointerover` target was unmounted from the scene graph.
1245
+ * @param propagationPath - The propagation path was valid in the past.
1246
+ * @returns - The most specific event-target still mounted at the same location in the scene graph.
1247
+ */
729
1248
  findMountedTarget(propagationPath) {
730
1249
  if (!propagationPath) {
731
1250
  return null;
732
1251
  }
733
1252
  let currentTarget = propagationPath[0];
734
1253
  for (let i = 1; i < propagationPath.length; i++) {
1254
+ // Set currentTarget to the next target in the path only if it is still attached to the
1255
+ // scene graph (i.e. parent still points to the expected ancestor).
735
1256
  if (propagationPath[i].parent === currentTarget) {
736
1257
  currentTarget = propagationPath[i];
737
1258
  }
@@ -741,6 +1262,14 @@ class EventBoundary {
741
1262
  }
742
1263
  return currentTarget;
743
1264
  }
1265
+ /**
1266
+ * Creates an event whose {@code originalEvent} is {@code from}, with an optional `type` and `target` override.
1267
+ *
1268
+ * The event is allocated using {@link EventBoundary#allocateEvent this.allocateEvent}.
1269
+ * @param from - The {@code originalEvent} for the returned event.
1270
+ * @param [type=from.type] - The type of the returned event.
1271
+ * @param target - The target of the returned event.
1272
+ */
744
1273
  createPointerEvent(from, type, target) {
745
1274
  var _a;
746
1275
  const event = this.allocateEvent(FederatedPointerEvent);
@@ -755,6 +1284,12 @@ class EventBoundary {
755
1284
  }
756
1285
  return event;
757
1286
  }
1287
+ /**
1288
+ * Creates a wheel event whose {@code originalEvent} is {@code from}.
1289
+ *
1290
+ * The event is allocated using {@link EventBoundary#allocateEvent this.allocateEvent}.
1291
+ * @param from - The upstream wheel event.
1292
+ */
758
1293
  createWheelEvent(from) {
759
1294
  const event = this.allocateEvent(FederatedWheelEvent);
760
1295
  this.copyWheelData(from, event);
@@ -765,6 +1300,13 @@ class EventBoundary {
765
1300
  event.target = this.hitTest(event.global.x, event.global.y);
766
1301
  return event;
767
1302
  }
1303
+ /**
1304
+ * Clones the event {@code from}, with an optional {@code type} override.
1305
+ *
1306
+ * The event is allocated using {@link EventBoundary#allocateEvent this.allocateEvent}.
1307
+ * @param from - The event to clone.
1308
+ * @param [type=from.type] - The type of the returned event.
1309
+ */
768
1310
  clonePointerEvent(from, type) {
769
1311
  const event = this.allocateEvent(FederatedPointerEvent);
770
1312
  event.nativeEvent = from.nativeEvent;
@@ -772,17 +1314,45 @@ class EventBoundary {
772
1314
  this.copyPointerData(from, event);
773
1315
  this.copyMouseData(from, event);
774
1316
  this.copyData(from, event);
1317
+ // copy propagation path for perf
775
1318
  event.target = from.target;
776
1319
  event.path = from.composedPath().slice();
777
1320
  event.type = type !== null && type !== void 0 ? type : event.type;
778
1321
  return event;
779
1322
  }
1323
+ /**
1324
+ * Copies wheel {@link FederatedWheelEvent} data from {@code from} into {@code to}.
1325
+ *
1326
+ * The following properties are copied:
1327
+ * + deltaMode
1328
+ * + deltaX
1329
+ * + deltaY
1330
+ * + deltaZ
1331
+ * @param from - The event to copy data from.
1332
+ * @param to - The event to copy data into.
1333
+ */
780
1334
  copyWheelData(from, to) {
781
1335
  to.deltaMode = from.deltaMode;
782
1336
  to.deltaX = from.deltaX;
783
1337
  to.deltaY = from.deltaY;
784
1338
  to.deltaZ = from.deltaZ;
785
1339
  }
1340
+ /**
1341
+ * Copies pointer {@link FederatedPointerEvent} data from {@code from} into {@code to}.
1342
+ *
1343
+ * The following properties are copied:
1344
+ * + pointerId
1345
+ * + width
1346
+ * + height
1347
+ * + isPrimary
1348
+ * + pointerType
1349
+ * + pressure
1350
+ * + tangentialPressure
1351
+ * + tiltX
1352
+ * + tiltY
1353
+ * @param from - The event to copy data from.
1354
+ * @param to - The event to copy data into.
1355
+ */
786
1356
  copyPointerData(from, to) {
787
1357
  if (!(from instanceof FederatedPointerEvent && to instanceof FederatedPointerEvent))
788
1358
  return;
@@ -797,6 +1367,28 @@ class EventBoundary {
797
1367
  to.tiltY = from.tiltY;
798
1368
  to.twist = from.twist;
799
1369
  }
1370
+ /**
1371
+ * Copies mouse {@link FederatedMouseEvent} data from {@code from} to {@code to}.
1372
+ *
1373
+ * The following properties are copied:
1374
+ * + altKey
1375
+ * + button
1376
+ * + buttons
1377
+ * + clientX
1378
+ * + clientY
1379
+ * + metaKey
1380
+ * + movementX
1381
+ * + movementY
1382
+ * + pageX
1383
+ * + pageY
1384
+ * + x
1385
+ * + y
1386
+ * + screen
1387
+ * + shiftKey
1388
+ * + global
1389
+ * @param from - The event to copy data from.
1390
+ * @param to - The event to copy data into.
1391
+ */
800
1392
  copyMouseData(from, to) {
801
1393
  if (!(from instanceof FederatedMouseEvent && to instanceof FederatedMouseEvent))
802
1394
  return;
@@ -811,6 +1403,17 @@ class EventBoundary {
811
1403
  to.shiftKey = from.shiftKey;
812
1404
  to.global.copyFrom(from.global);
813
1405
  }
1406
+ /**
1407
+ * Copies base {@link FederatedEvent} data from {@code from} into {@code to}.
1408
+ *
1409
+ * The following properties are copied:
1410
+ * + isTrusted
1411
+ * + srcElement
1412
+ * + timeStamp
1413
+ * + type
1414
+ * @param from - The event to copy data from.
1415
+ * @param to - The event to copy data into.
1416
+ */
814
1417
  copyData(from, to) {
815
1418
  to.isTrusted = from.isTrusted;
816
1419
  to.srcElement = from.srcElement;
@@ -822,6 +1425,11 @@ class EventBoundary {
822
1425
  to.layer.copyFrom(from.layer);
823
1426
  to.page.copyFrom(from.page);
824
1427
  }
1428
+ /**
1429
+ * @param id - The pointer ID.
1430
+ * @returns The tracking data stored for the given pointer. If no data exists, a blank
1431
+ * state will be created.
1432
+ */
825
1433
  trackingData(id) {
826
1434
  if (!this.mappingState.trackingData[id]) {
827
1435
  this.mappingState.trackingData[id] = {
@@ -832,6 +1440,13 @@ class EventBoundary {
832
1440
  }
833
1441
  return this.mappingState.trackingData[id];
834
1442
  }
1443
+ /**
1444
+ * Allocate a specific type of event from {@link EventBoundary#eventPool this.eventPool}.
1445
+ *
1446
+ * This allocation is constructor-agnostic, as long as it only takes one argument - this event
1447
+ * boundary.
1448
+ * @param constructor - The event's constructor.
1449
+ */
835
1450
  allocateEvent(constructor) {
836
1451
  if (!this.eventPool.has(constructor)) {
837
1452
  this.eventPool.set(constructor, []);
@@ -844,6 +1459,17 @@ class EventBoundary {
844
1459
  event.target = null;
845
1460
  return event;
846
1461
  }
1462
+ /**
1463
+ * Frees the event and puts it back into the event pool.
1464
+ *
1465
+ * It is illegal to reuse the event until it is allocated again, using `this.allocateEvent`.
1466
+ *
1467
+ * It is also advised that events not allocated from {@link EventBoundary#allocateEvent this.allocateEvent}
1468
+ * not be freed. This is because of the possibility that the same event is freed twice, which can cause
1469
+ * it to be allocated twice & result in overwriting.
1470
+ * @param event - The event to be freed.
1471
+ * @throws Error if the event is managed by another event boundary.
1472
+ */
847
1473
  freeEvent(event) {
848
1474
  if (event.manager !== this)
849
1475
  throw new Error('It is illegal to free an event not managed by this EventBoundary!');
@@ -853,6 +1479,12 @@ class EventBoundary {
853
1479
  }
854
1480
  this.eventPool.get(constructor).push(event);
855
1481
  }
1482
+ /**
1483
+ * Similar to {@link EventEmitter.emit}, except it stops if the `propagationImmediatelyStopped` flag
1484
+ * is set on the event.
1485
+ * @param e - The event to call each listener with.
1486
+ * @param type - The event key.
1487
+ */
856
1488
  _notifyListeners(e, type) {
857
1489
  const listeners = e.currentTarget._events[type];
858
1490
  if (!listeners)
@@ -879,11 +1511,47 @@ const TOUCH_TO_POINTER = {
879
1511
  touchmove: 'pointermove',
880
1512
  touchcancel: 'pointercancel',
881
1513
  };
1514
+ /**
1515
+ * 事件系统类
1516
+ *
1517
+ * EventSystem 负责处理所有 UI 交互事件(鼠标、触摸、指针等)。
1518
+ * 它将原生 DOM 事件转换为统一的 FederatedEvent,
1519
+ * 并通过事件边界(EventBoundary)将事件传播到场景图中的对象。
1520
+ *
1521
+ * 支持的事件类型:
1522
+ * - 指针事件:pointerdown、pointermove、pointerup 等
1523
+ * - 鼠标事件:mousedown、mousemove、mouseup 等
1524
+ * - 触摸事件:touchstart、touchmove、touchend 等
1525
+ * - 滚轮事件:wheel
1526
+ *
1527
+ * @example
1528
+ * ```typescript
1529
+ * const eventSystem = new EventSystem(renderer);
1530
+ * eventSystem.init({
1531
+ * eventMode: 'passive',
1532
+ * eventFeatures: {
1533
+ * move: true,
1534
+ * click: true,
1535
+ * wheel: true
1536
+ * }
1537
+ * });
1538
+ * ```
1539
+ */
882
1540
  class EventSystem {
1541
+ /**
1542
+ * @param {Renderer} renderer
1543
+ */
883
1544
  constructor(renderer) {
1545
+ /** Does the device support touch events https://www.w3.org/TR/touch-events/ */
884
1546
  this.supportsTouchEvents = 'ontouchstart' in globalThis;
1547
+ /** Does the device support pointer events https://www.w3.org/Submission/pointer-events/ */
885
1548
  this.supportsPointerEvents = !!globalThis.PointerEvent;
1549
+ /**
1550
+ * The DOM element to which the root event listeners are bound. This is automatically set to
1551
+ * the renderer's {@link Renderer#view view}.
1552
+ */
886
1553
  this.domElement = null;
1554
+ /** The resolution used to convert between the DOM client space into world space. */
887
1555
  this.resolution = 1;
888
1556
  this.renderer = renderer;
889
1557
  this.rootBoundary = new EventBoundary(null);
@@ -911,9 +1579,20 @@ class EventSystem {
911
1579
  this._onPointerOverOut = this._onPointerOverOut.bind(this);
912
1580
  this.onWheel = this.onWheel.bind(this);
913
1581
  }
1582
+ /**
1583
+ * The default interaction mode for all display objects.
1584
+ * @see Container.eventMode
1585
+ * @type {EventMode}
1586
+ * @readonly
1587
+ * @since 7.2.0
1588
+ */
914
1589
  static get defaultEventMode() {
915
1590
  return this._defaultEventMode;
916
1591
  }
1592
+ /**
1593
+ * Runner init called, view is available at this point.
1594
+ * @ignore
1595
+ */
917
1596
  init(options) {
918
1597
  var _a, _b;
919
1598
  const { canvas, resolution } = this.renderer;
@@ -923,38 +1602,55 @@ class EventSystem {
923
1602
  Object.assign(this.features, (_b = options.eventFeatures) !== null && _b !== void 0 ? _b : {});
924
1603
  this.rootBoundary.enableGlobalMoveEvents = this.features.globalMove;
925
1604
  }
1605
+ /**
1606
+ * Handle changing resolution.
1607
+ * @ignore
1608
+ */
926
1609
  resolutionChange(resolution) {
927
1610
  this.resolution = resolution;
928
1611
  }
1612
+ /** Destroys all event listeners and detaches the renderer. */
929
1613
  destroy() {
930
1614
  this.setTargetElement(null);
931
1615
  this.renderer = null;
932
1616
  this._currentCursor = null;
933
1617
  }
1618
+ /**
1619
+ * Sets the current cursor mode, handling any callbacks or CSS style changes.
1620
+ * @param mode - cursor mode, a key from the cursorStyles dictionary
1621
+ */
934
1622
  setCursor(mode) {
935
1623
  if (!mode) {
936
1624
  mode = 'default';
937
1625
  }
938
1626
  let applyStyles = true;
1627
+ // offscreen canvas does not support setting styles, but cursor modes can be functions,
1628
+ // in order to handle pixi rendered cursors, so we can't bail
939
1629
  if (globalThis.OffscreenCanvas && this.domElement instanceof OffscreenCanvas) {
940
1630
  applyStyles = false;
941
1631
  }
1632
+ // if the mode didn't actually change, bail early
942
1633
  if (this._currentCursor === mode) {
943
1634
  return;
944
1635
  }
945
1636
  this._currentCursor = mode;
946
1637
  const style = this.cursorStyles[mode];
1638
+ // only do things if there is a cursor style for it
947
1639
  if (style) {
948
1640
  switch (typeof style) {
949
1641
  case 'string':
1642
+ // string styles are handled as cursor CSS
950
1643
  if (applyStyles) {
951
1644
  this.domElement.style.cursor = style;
952
1645
  }
953
1646
  break;
954
1647
  case 'function':
1648
+ // functions are just called, and passed the cursor mode
955
1649
  style(mode);
956
1650
  break;
957
1651
  case 'object':
1652
+ // if it is an object, assume that it is a dictionary of CSS styles,
1653
+ // apply it to the interactionDOMElement
958
1654
  if (applyStyles) {
959
1655
  Object.assign(this.domElement.style, style);
960
1656
  }
@@ -964,17 +1660,34 @@ class EventSystem {
964
1660
  else if (applyStyles &&
965
1661
  typeof mode === 'string' &&
966
1662
  !Object.prototype.hasOwnProperty.call(this.cursorStyles, mode)) {
1663
+ // if it mode is a string (not a Symbol) and cursorStyles doesn't have any entry
1664
+ // for the mode, then assume that the dev wants it to be CSS for the cursor.
967
1665
  this.domElement.style.cursor = mode;
968
1666
  }
969
1667
  }
1668
+ /**
1669
+ * The global pointer event.
1670
+ * Useful for getting the pointer position without listening to events.
1671
+ * @since 7.2.0
1672
+ */
970
1673
  get pointer() {
971
1674
  return this._rootPointerEvent;
972
1675
  }
1676
+ /**
1677
+ * Event handler for pointer down events on {@link EventSystem#domElement this.domElement}.
1678
+ * @param nativeEvent - The native mouse/pointer/touch event.
1679
+ */
973
1680
  _onPointerDown(nativeEvent) {
974
1681
  if (!this.features.click)
975
1682
  return;
976
1683
  this.rootBoundary.rootTarget = this.renderer.lastObjectRendered;
977
1684
  const events = this._normalizeToPointerData(nativeEvent);
1685
+ /*
1686
+ * No need to prevent default on natural pointer events, as there are no side effects
1687
+ * Normalized events, however, may have the double mousedown/touchstart issue on the native android browser,
1688
+ * so still need to be prevented.
1689
+ */
1690
+ // Guaranteed that there will be at least one event in events, and all events must have the same pointer type
978
1691
  if (this.autoPreventDefault && events[0].isNormalized) {
979
1692
  const cancelable = nativeEvent.cancelable || !('cancelable' in nativeEvent);
980
1693
  if (cancelable) {
@@ -989,6 +1702,10 @@ class EventSystem {
989
1702
  }
990
1703
  this.setCursor(this.rootBoundary.cursor);
991
1704
  }
1705
+ /**
1706
+ * Event handler for pointer move events on on {@link EventSystem#domElement this.domElement}.
1707
+ * @param nativeEvent - The native mouse/pointer/touch events.
1708
+ */
992
1709
  _onPointerMove(nativeEvent) {
993
1710
  if (!this.features.move)
994
1711
  return;
@@ -1001,6 +1718,10 @@ class EventSystem {
1001
1718
  }
1002
1719
  this.setCursor(this.rootBoundary.cursor);
1003
1720
  }
1721
+ /**
1722
+ * Event handler for pointer up events on {@link EventSystem#domElement this.domElement}.
1723
+ * @param nativeEvent - The native mouse/pointer/touch event.
1724
+ */
1004
1725
  _onPointerUp(nativeEvent) {
1005
1726
  if (!this.features.click)
1006
1727
  return;
@@ -1014,6 +1735,10 @@ class EventSystem {
1014
1735
  }
1015
1736
  this.setCursor(this.rootBoundary.cursor);
1016
1737
  }
1738
+ /**
1739
+ * Event handler for pointer over & out events on {@link EventSystem#domElement this.domElement}.
1740
+ * @param nativeEvent - The native mouse/pointer/touch event.
1741
+ */
1017
1742
  _onPointerOverOut(nativeEvent) {
1018
1743
  if (!this.features.click)
1019
1744
  return;
@@ -1025,6 +1750,10 @@ class EventSystem {
1025
1750
  }
1026
1751
  this.setCursor(this.rootBoundary.cursor);
1027
1752
  }
1753
+ /**
1754
+ * Passive handler for `wheel` events on {@link EventSystem.domElement this.domElement}.
1755
+ * @param nativeEvent - The native wheel event.
1756
+ */
1028
1757
  onWheel(nativeEvent) {
1029
1758
  if (!this.features.wheel)
1030
1759
  return;
@@ -1032,12 +1761,19 @@ class EventSystem {
1032
1761
  this.rootBoundary.rootTarget = this.renderer.lastObjectRendered;
1033
1762
  this.rootBoundary.mapEvent(wheelEvent);
1034
1763
  }
1764
+ /**
1765
+ * Sets the {@link EventSystem#domElement domElement} and binds event listeners.
1766
+ *
1767
+ * To deregister the current DOM element without setting a new one, pass {@code null}.
1768
+ * @param element - The new DOM element.
1769
+ */
1035
1770
  setTargetElement(element) {
1036
1771
  this._removeEvents();
1037
1772
  this.domElement = element;
1038
1773
  EventsTicker.domElement = element;
1039
1774
  this._addEvents();
1040
1775
  }
1776
+ /** Register event listeners on {@link Renderer#domElement this.domElement}. */
1041
1777
  _addEvents() {
1042
1778
  if (this._eventsAdded || !this.domElement) {
1043
1779
  return;
@@ -1060,6 +1796,10 @@ class EventSystem {
1060
1796
  id = key;
1061
1797
  }
1062
1798
  }
1799
+ /*
1800
+ * These events are added first, so that if pointer events are normalized, they are fired
1801
+ * in the same order as non-normalized events. ie. pointer event 1st, mouse / touch 2nd
1802
+ */
1063
1803
  EventSystem.eventsHandler[id] = {
1064
1804
  pointermove: this._onPointerMove.bind(this),
1065
1805
  pointerdown: this._onPointerDown.bind(this),
@@ -1078,12 +1818,14 @@ class EventSystem {
1078
1818
  EventSystem.eventsHandler[id]['wheel'] = this.onWheel.bind(this);
1079
1819
  this._eventsAdded = true;
1080
1820
  }
1821
+ /** Unregister event listeners on {@link EventSystem#domElement this.domElement}. */
1081
1822
  _removeEvents() {
1082
1823
  if (!this._eventsAdded || !this.domElement) {
1083
1824
  return;
1084
1825
  }
1085
1826
  EventsTicker.removeTickerListener();
1086
1827
  const style = this.domElement.style;
1828
+ // offscreen canvas does not have style, so check first
1087
1829
  if (style) {
1088
1830
  if (globalThis.navigator.msPointerEnabled) {
1089
1831
  style.msContentZooming = '';
@@ -1096,6 +1838,14 @@ class EventSystem {
1096
1838
  this.domElement = null;
1097
1839
  this._eventsAdded = false;
1098
1840
  }
1841
+ /**
1842
+ * Maps x and y coords from a DOM object and maps them correctly to the PixiJS view. The
1843
+ * resulting value is stored in the point. This takes into account the fact that the DOM
1844
+ * element could be scaled and positioned anywhere on the screen.
1845
+ * @param {PointData} point - the point that the result will be stored in
1846
+ * @param {number} x - the x coord of the position to map
1847
+ * @param {number} y - the y coord of the position to map
1848
+ */
1099
1849
  mapPositionToPoint(point, x, y, e) {
1100
1850
  const resolutionMultiplier = 1.0 / this.resolution;
1101
1851
  const rect = e.canvasRect || {
@@ -1110,12 +1860,34 @@ class EventSystem {
1110
1860
  point.x = (x - rect.left) * (domElement.width / rect.width) * resolutionMultiplier;
1111
1861
  point.y = (y - rect.top) * (domElement.height / rect.height) * resolutionMultiplier;
1112
1862
  }
1863
+ /**
1864
+ * Ensures that the original event object contains all data that a regular pointer event would have
1865
+ * @param event - The original event data from a touch or mouse event
1866
+ * @returns An array containing a single normalized pointer event, in the case of a pointer
1867
+ * or mouse event, or a multiple normalized pointer events if there are multiple changed touches
1868
+ */
1113
1869
  _normalizeToPointerData(event) {
1870
+ // @ts-ignore
1114
1871
  return event.normalizedEvents;
1115
1872
  }
1873
+ /**
1874
+ * Normalizes the native {@link https://w3c.github.io/uievents/#interface-wheelevent WheelEvent}.
1875
+ *
1876
+ * The returned {@link FederatedWheelEvent} is a shared instance. It will not persist across
1877
+ * multiple native wheel events.
1878
+ * @param nativeEvent - The native wheel event that occurred on the canvas.
1879
+ * @returns A federated wheel event.
1880
+ */
1116
1881
  normalizeWheelEvent(nativeEvent) {
1117
1882
  const event = this._rootWheelEvent;
1118
1883
  this._transferMouseData(event, nativeEvent);
1884
+ // When WheelEvent is triggered by scrolling with mouse wheel, reading WheelEvent.deltaMode
1885
+ // before deltaX/deltaY/deltaZ on Firefox will result in WheelEvent.DOM_DELTA_LINE (1),
1886
+ // while reading WheelEvent.deltaMode after deltaX/deltaY/deltaZ on Firefox or reading
1887
+ // in any order on other browsers will result in WheelEvent.DOM_DELTA_PIXEL (0).
1888
+ // Therefore, we need to read WheelEvent.deltaMode after deltaX/deltaY/deltaZ in order to
1889
+ // make its behavior more consistent across browsers.
1890
+ // @see https://github.com/pixijs/pixijs/issues/8970
1119
1891
  event.deltaX = nativeEvent.deltaX;
1120
1892
  event.deltaY = nativeEvent.deltaY;
1121
1893
  event.deltaZ = nativeEvent.deltaZ;
@@ -1127,6 +1899,11 @@ class EventSystem {
1127
1899
  event.type = nativeEvent.type;
1128
1900
  return event;
1129
1901
  }
1902
+ /**
1903
+ * Normalizes the `nativeEvent` into a federateed {@link FederatedPointerEvent}.
1904
+ * @param event
1905
+ * @param nativeEvent
1906
+ */
1130
1907
  _bootstrapEvent(event, nativeEvent, nEvent) {
1131
1908
  event.originalEvent = null;
1132
1909
  event.nativeEvent = nativeEvent;
@@ -1142,8 +1919,8 @@ class EventSystem {
1142
1919
  event.twist = nativeEvent.twist;
1143
1920
  this._transferMouseData(event, nativeEvent);
1144
1921
  this.mapPositionToPoint(event.screen, nativeEvent.clientX, nativeEvent.clientY, nEvent);
1145
- event.global.copyFrom(event.screen);
1146
- event.offset.copyFrom(event.screen);
1922
+ event.global.copyFrom(event.screen); // global = screen for top-level
1923
+ event.offset.copyFrom(event.screen); // EventBoundary recalculates using its rootTarget
1147
1924
  event.isTrusted = nativeEvent.isTrusted;
1148
1925
  if (event.type === 'pointerleave') {
1149
1926
  event.type = 'pointerout';
@@ -1156,6 +1933,11 @@ class EventSystem {
1156
1933
  }
1157
1934
  return event;
1158
1935
  }
1936
+ /**
1937
+ * Transfers base & mouse event data from the {@code nativeEvent} to the federated event.
1938
+ * @param event
1939
+ * @param nativeEvent
1940
+ */
1159
1941
  _transferMouseData(event, nativeEvent) {
1160
1942
  event.isTrusted = nativeEvent.isTrusted;
1161
1943
  event.srcElement = nativeEvent.srcElement;
@@ -1176,61 +1958,397 @@ class EventSystem {
1176
1958
  event.shiftKey = nativeEvent.shiftKey;
1177
1959
  }
1178
1960
  }
1961
+ /** @ignore */
1179
1962
  EventSystem.extension = {
1180
1963
  name: 'events',
1181
1964
  type: [ExtensionType.WebGLSystem, ExtensionType.CanvasSystem, ExtensionType.WebGPUSystem],
1182
1965
  priority: -1,
1183
1966
  };
1967
+ /** 画布映射表 */
1184
1968
  EventSystem.canvasMap = {};
1969
+ /** 事件处理器映射表 */
1185
1970
  EventSystem.eventsHandler = {};
1971
+ /**
1972
+ * 事件系统的默认功能配置
1973
+ * @since 7.2.0
1974
+ */
1186
1975
  EventSystem.defaultEventFeatures = {
1976
+ /** 启用指针移动相关事件 */
1187
1977
  move: true,
1978
+ /** 启用全局指针移动事件 */
1188
1979
  globalMove: true,
1980
+ /** 启用点击相关事件 */
1189
1981
  click: true,
1982
+ /** 启用滚轮事件 */
1190
1983
  wheel: true,
1191
1984
  };
1192
1985
 
1193
1986
  const FederatedContainer = {
1987
+ /**
1988
+ * Property-based event handler for the `click` event.
1989
+ * @memberof scene.Container#
1990
+ * @default null
1991
+ * @example
1992
+ * this.onclick = (event) => {
1993
+ * //some function here that happens on click
1994
+ * }
1995
+ */
1194
1996
  onclick: null,
1997
+ /**
1998
+ * Property-based event handler for the `mousedown` event.
1999
+ * @memberof scene.Container#
2000
+ * @default null
2001
+ * @example
2002
+ * this.onmousedown = (event) => {
2003
+ * //some function here that happens on mousedown
2004
+ * }
2005
+ */
1195
2006
  onmousedown: null,
2007
+ /**
2008
+ * Property-based event handler for the `mouseenter` event.
2009
+ * @memberof scene.Container#
2010
+ * @default null
2011
+ * @example
2012
+ * this.onmouseenter = (event) => {
2013
+ * //some function here that happens on mouseenter
2014
+ * }
2015
+ */
1196
2016
  onmouseenter: null,
2017
+ /**
2018
+ * Property-based event handler for the `mouseleave` event.
2019
+ * @memberof scene.Container#
2020
+ * @default null
2021
+ * @example
2022
+ * this.onmouseleave = (event) => {
2023
+ * //some function here that happens on mouseleave
2024
+ * }
2025
+ */
1197
2026
  onmouseleave: null,
2027
+ /**
2028
+ * Property-based event handler for the `mousemove` event.
2029
+ * @memberof scene.Container#
2030
+ * @default null
2031
+ * @example
2032
+ * this.onmousemove = (event) => {
2033
+ * //some function here that happens on mousemove
2034
+ * }
2035
+ */
1198
2036
  onmousemove: null,
2037
+ /**
2038
+ * Property-based event handler for the `globalmousemove` event.
2039
+ * @memberof scene.Container#
2040
+ * @default null
2041
+ * @example
2042
+ * this.onglobalmousemove = (event) => {
2043
+ * //some function here that happens on globalmousemove
2044
+ * }
2045
+ */
1199
2046
  onglobalmousemove: null,
2047
+ /**
2048
+ * Property-based event handler for the `mouseout` event.
2049
+ * @memberof scene.Container#
2050
+ * @default null
2051
+ * @example
2052
+ * this.onmouseout = (event) => {
2053
+ * //some function here that happens on mouseout
2054
+ * }
2055
+ */
1200
2056
  onmouseout: null,
2057
+ /**
2058
+ * Property-based event handler for the `mouseover` event.
2059
+ * @memberof scene.Container#
2060
+ * @default null
2061
+ * @example
2062
+ * this.onmouseover = (event) => {
2063
+ * //some function here that happens on mouseover
2064
+ * }
2065
+ */
1201
2066
  onmouseover: null,
2067
+ /**
2068
+ * Property-based event handler for the `mouseup` event.
2069
+ * @memberof scene.Container#
2070
+ * @default null
2071
+ * @example
2072
+ * this.onmouseup = (event) => {
2073
+ * //some function here that happens on mouseup
2074
+ * }
2075
+ */
1202
2076
  onmouseup: null,
2077
+ /**
2078
+ * Property-based event handler for the `mouseupoutside` event.
2079
+ * @memberof scene.Container#
2080
+ * @default null
2081
+ * @example
2082
+ * this.onmouseupoutside = (event) => {
2083
+ * //some function here that happens on mouseupoutside
2084
+ * }
2085
+ */
1203
2086
  onmouseupoutside: null,
2087
+ /**
2088
+ * Property-based event handler for the `pointercancel` event.
2089
+ * @memberof scene.Container#
2090
+ * @default null
2091
+ * @example
2092
+ * this.onpointercancel = (event) => {
2093
+ * //some function here that happens on pointercancel
2094
+ * }
2095
+ */
1204
2096
  onpointercancel: null,
2097
+ /**
2098
+ * Property-based event handler for the `pointerdown` event.
2099
+ * @memberof scene.Container#
2100
+ * @default null
2101
+ * @example
2102
+ * this.onpointerdown = (event) => {
2103
+ * //some function here that happens on pointerdown
2104
+ * }
2105
+ */
1205
2106
  onpointerdown: null,
2107
+ /**
2108
+ * Property-based event handler for the `pointerenter` event.
2109
+ * @memberof scene.Container#
2110
+ * @default null
2111
+ * @example
2112
+ * this.onpointerenter = (event) => {
2113
+ * //some function here that happens on pointerenter
2114
+ * }
2115
+ */
1206
2116
  onpointerenter: null,
2117
+ /**
2118
+ * Property-based event handler for the `pointerleave` event.
2119
+ * @memberof scene.Container#
2120
+ * @default null
2121
+ * @example
2122
+ * this.onpointerleave = (event) => {
2123
+ * //some function here that happens on pointerleave
2124
+ * }
2125
+ */
1207
2126
  onpointerleave: null,
2127
+ /**
2128
+ * Property-based event handler for the `pointermove` event.
2129
+ * @memberof scene.Container#
2130
+ * @default null
2131
+ * @example
2132
+ * this.onpointermove = (event) => {
2133
+ * //some function here that happens on pointermove
2134
+ * }
2135
+ */
1208
2136
  onpointermove: null,
2137
+ /**
2138
+ * Property-based event handler for the `globalpointermove` event.
2139
+ * @memberof scene.Container#
2140
+ * @default null
2141
+ * @example
2142
+ * this.onglobalpointermove = (event) => {
2143
+ * //some function here that happens on globalpointermove
2144
+ * }
2145
+ */
1209
2146
  onglobalpointermove: null,
2147
+ /**
2148
+ * Property-based event handler for the `pointerout` event.
2149
+ * @memberof scene.Container#
2150
+ * @default null
2151
+ * @example
2152
+ * this.onpointerout = (event) => {
2153
+ * //some function here that happens on pointerout
2154
+ * }
2155
+ */
1210
2156
  onpointerout: null,
2157
+ /**
2158
+ * Property-based event handler for the `pointerover` event.
2159
+ * @memberof scene.Container#
2160
+ * @default null
2161
+ * @example
2162
+ * this.onpointerover = (event) => {
2163
+ * //some function here that happens on pointerover
2164
+ * }
2165
+ */
1211
2166
  onpointerover: null,
2167
+ /**
2168
+ * Property-based event handler for the `pointertap` event.
2169
+ * @memberof scene.Container#
2170
+ * @default null
2171
+ * @example
2172
+ * this.onpointertap = (event) => {
2173
+ * //some function here that happens on pointertap
2174
+ * }
2175
+ */
1212
2176
  onpointertap: null,
2177
+ /**
2178
+ * Property-based event handler for the `pointerup` event.
2179
+ * @memberof scene.Container#
2180
+ * @default null
2181
+ * @example
2182
+ * this.onpointerup = (event) => {
2183
+ * //some function here that happens on pointerup
2184
+ * }
2185
+ */
1213
2186
  onpointerup: null,
2187
+ /**
2188
+ * Property-based event handler for the `pointerupoutside` event.
2189
+ * @memberof scene.Container#
2190
+ * @default null
2191
+ * @example
2192
+ * this.onpointerupoutside = (event) => {
2193
+ * //some function here that happens on pointerupoutside
2194
+ * }
2195
+ */
1214
2196
  onpointerupoutside: null,
2197
+ /**
2198
+ * Property-based event handler for the `rightclick` event.
2199
+ * @memberof scene.Container#
2200
+ * @default null
2201
+ * @example
2202
+ * this.onrightclick = (event) => {
2203
+ * //some function here that happens on rightclick
2204
+ * }
2205
+ */
1215
2206
  onrightclick: null,
2207
+ /**
2208
+ * Property-based event handler for the `rightdown` event.
2209
+ * @memberof scene.Container#
2210
+ * @default null
2211
+ * @example
2212
+ * this.onrightdown = (event) => {
2213
+ * //some function here that happens on rightdown
2214
+ * }
2215
+ */
1216
2216
  onrightdown: null,
2217
+ /**
2218
+ * Property-based event handler for the `rightup` event.
2219
+ * @memberof scene.Container#
2220
+ * @default null
2221
+ * @example
2222
+ * this.onrightup = (event) => {
2223
+ * //some function here that happens on rightup
2224
+ * }
2225
+ */
1217
2226
  onrightup: null,
2227
+ /**
2228
+ * Property-based event handler for the `rightupoutside` event.
2229
+ * @memberof scene.Container#
2230
+ * @default null
2231
+ * @example
2232
+ * this.onrightupoutside = (event) => {
2233
+ * //some function here that happens on rightupoutside
2234
+ * }
2235
+ */
1218
2236
  onrightupoutside: null,
2237
+ /**
2238
+ * Property-based event handler for the `tap` event.
2239
+ * @memberof scene.Container#
2240
+ * @default null
2241
+ * @example
2242
+ * this.ontap = (event) => {
2243
+ * //some function here that happens on tap
2244
+ * }
2245
+ */
1219
2246
  ontap: null,
2247
+ /**
2248
+ * Property-based event handler for the `touchcancel` event.
2249
+ * @memberof scene.Container#
2250
+ * @default null
2251
+ * @example
2252
+ * this.ontouchcancel = (event) => {
2253
+ * //some function here that happens on touchcancel
2254
+ * }
2255
+ */
1220
2256
  ontouchcancel: null,
2257
+ /**
2258
+ * Property-based event handler for the `touchend` event.
2259
+ * @memberof scene.Container#
2260
+ * @default null
2261
+ * @example
2262
+ * this.ontouchend = (event) => {
2263
+ * //some function here that happens on touchend
2264
+ * }
2265
+ */
1221
2266
  ontouchend: null,
2267
+ /**
2268
+ * Property-based event handler for the `touchendoutside` event.
2269
+ * @memberof scene.Container#
2270
+ * @default null
2271
+ * @example
2272
+ * this.ontouchendoutside = (event) => {
2273
+ * //some function here that happens on touchendoutside
2274
+ * }
2275
+ */
1222
2276
  ontouchendoutside: null,
2277
+ /**
2278
+ * Property-based event handler for the `touchmove` event.
2279
+ * @memberof scene.Container#
2280
+ * @default null
2281
+ * @example
2282
+ * this.ontouchmove = (event) => {
2283
+ * //some function here that happens on touchmove
2284
+ * }
2285
+ */
1223
2286
  ontouchmove: null,
2287
+ /**
2288
+ * Property-based event handler for the `globaltouchmove` event.
2289
+ * @memberof scene.Container#
2290
+ * @default null
2291
+ * @example
2292
+ * this.onglobaltouchmove = (event) => {
2293
+ * //some function here that happens on globaltouchmove
2294
+ * }
2295
+ */
1224
2296
  onglobaltouchmove: null,
2297
+ /**
2298
+ * Property-based event handler for the `touchstart` event.
2299
+ * @memberof scene.Container#
2300
+ * @default null
2301
+ * @example
2302
+ * this.ontouchstart = (event) => {
2303
+ * //some function here that happens on touchstart
2304
+ * }
2305
+ */
1225
2306
  ontouchstart: null,
2307
+ /**
2308
+ * Property-based event handler for the `wheel` event.
2309
+ * @memberof scene.Container#
2310
+ * @default null
2311
+ * @example
2312
+ * this.onwheel = (event) => {
2313
+ * //some function here that happens on wheel
2314
+ * }
2315
+ */
1226
2316
  onwheel: null,
2317
+ /**
2318
+ * Enable interaction events for the Container. Touch, pointer and mouse
2319
+ * @memberof scene.Container#
2320
+ */
1227
2321
  get interactive() {
1228
2322
  return this.eventMode === 'dynamic' || this.eventMode === 'static';
1229
2323
  },
1230
2324
  set interactive(value) {
1231
2325
  this.eventMode = value ? 'static' : 'passive';
1232
2326
  },
2327
+ /**
2328
+ * @ignore
2329
+ */
1233
2330
  _internalEventMode: undefined,
2331
+ /**
2332
+ * Enable interaction events for the Container. Touch, pointer and mouse.
2333
+ * There are 5 types of interaction settings:
2334
+ * - `'none'`: Ignores all interaction events, even on its children.
2335
+ * - `'passive'`: **(default)** Does not emit events and ignores all hit testing on itself and non-interactive children.
2336
+ * Interactive children will still emit events.
2337
+ * - `'auto'`: Does not emit events but is hit tested if parent is interactive. Same as `interactive = false` in v7
2338
+ * - `'static'`: Emit events and is hit tested. Same as `interaction = true` in v7
2339
+ * - `'dynamic'`: Emits events and is hit tested but will also receive mock interaction events fired from a ticker to
2340
+ * allow for interaction when the mouse isn't moving
2341
+ * @example
2342
+ * import { Sprite } from 'pixi.js';
2343
+ *
2344
+ * const sprite = new Sprite(texture);
2345
+ * sprite.eventMode = 'static';
2346
+ * sprite.on('tap', (event) => {
2347
+ * // Handle event
2348
+ * });
2349
+ * @memberof scene.Container#
2350
+ * @since 7.2.0
2351
+ */
1234
2352
  get eventMode() {
1235
2353
  var _a;
1236
2354
  return (_a = this._internalEventMode) !== null && _a !== void 0 ? _a : EventSystem.defaultEventMode;
@@ -1238,11 +2356,84 @@ const FederatedContainer = {
1238
2356
  set eventMode(value) {
1239
2357
  this._internalEventMode = value;
1240
2358
  },
2359
+ /**
2360
+ * Determines if the container is interactive or not
2361
+ * @returns {boolean} Whether the container is interactive or not
2362
+ * @memberof scene.Container#
2363
+ * @since 7.2.0
2364
+ * @example
2365
+ * import { Sprite } from 'pixi.js';
2366
+ *
2367
+ * const sprite = new Sprite(texture);
2368
+ * sprite.eventMode = 'static';
2369
+ * sprite.isInteractive(); // true
2370
+ *
2371
+ * sprite.eventMode = 'dynamic';
2372
+ * sprite.isInteractive(); // true
2373
+ *
2374
+ * sprite.eventMode = 'none';
2375
+ * sprite.isInteractive(); // false
2376
+ *
2377
+ * sprite.eventMode = 'passive';
2378
+ * sprite.isInteractive(); // false
2379
+ *
2380
+ * sprite.eventMode = 'auto';
2381
+ * sprite.isInteractive(); // false
2382
+ */
1241
2383
  isInteractive() {
1242
2384
  return this.eventMode === 'static' || this.eventMode === 'dynamic';
1243
2385
  },
2386
+ /**
2387
+ * Determines if the children to the container can be clicked/touched
2388
+ * Setting this to false allows PixiJS to bypass a recursive `hitTest` function
2389
+ * @memberof scene.Container#
2390
+ */
1244
2391
  interactiveChildren: true,
2392
+ /**
2393
+ * Interaction shape. Children will be hit first, then this shape will be checked.
2394
+ * Setting this will cause this shape to be checked in hit tests rather than the container's bounds.
2395
+ * @example
2396
+ * import { Rectangle, Sprite } from 'pixi.js';
2397
+ *
2398
+ * const sprite = new Sprite(texture);
2399
+ * sprite.interactive = true;
2400
+ * sprite.hitArea = new Rectangle(0, 0, 100, 100);
2401
+ * @member {IHitArea}
2402
+ * @memberof scene.Container#
2403
+ */
1245
2404
  hitArea: null,
2405
+ /**
2406
+ * Unlike `on` or `addListener` which are methods from EventEmitter, `addEventListener`
2407
+ * seeks to be compatible with the DOM's `addEventListener` with support for options.
2408
+ * @memberof scene.Container
2409
+ * @param type - The type of event to listen to.
2410
+ * @param listener - The listener callback or object.
2411
+ * @param options - Listener options, used for capture phase.
2412
+ * @example
2413
+ * // Tell the user whether they did a single, double, triple, or nth click.
2414
+ * button.addEventListener('click', {
2415
+ * handleEvent(e): {
2416
+ * let prefix;
2417
+ *
2418
+ * switch (e.detail) {
2419
+ * case 1: prefix = 'single'; break;
2420
+ * case 2: prefix = 'double'; break;
2421
+ * case 3: prefix = 'triple'; break;
2422
+ * default: prefix = e.detail + 'th'; break;
2423
+ * }
2424
+ *
2425
+ * console.log('That was a ' + prefix + 'click');
2426
+ * }
2427
+ * });
2428
+ *
2429
+ * // But skip the first click!
2430
+ * button.parent.addEventListener('click', function blockClickOnce(e) {
2431
+ * e.stopImmediatePropagation();
2432
+ * button.parent.removeEventListener('click', blockClickOnce, true);
2433
+ * }, {
2434
+ * capture: true,
2435
+ * });
2436
+ */
1246
2437
  addEventListener(type, listener, options) {
1247
2438
  const capture = (typeof options === 'boolean' && options) || (typeof options === 'object' && options.capture);
1248
2439
  const signal = typeof options === 'object' ? options.signal : undefined;
@@ -1263,6 +2454,14 @@ const FederatedContainer = {
1263
2454
  emitter.on(type, listenerFn, context);
1264
2455
  }
1265
2456
  },
2457
+ /**
2458
+ * Unlike `off` or `removeListener` which are methods from EventEmitter, `removeEventListener`
2459
+ * seeks to be compatible with the DOM's `removeEventListener` with support for options.
2460
+ * @memberof scene.Container
2461
+ * @param type - The type of event the listener is bound to.
2462
+ * @param listener - The listener callback or object.
2463
+ * @param options - The original listener options. This is required to deregister a capture phase listener.
2464
+ */
1266
2465
  removeEventListener(type, listener, options) {
1267
2466
  const capture = (typeof options === 'boolean' && options) || (typeof options === 'object' && options.capture);
1268
2467
  const context = typeof listener === 'function' ? undefined : listener;
@@ -1270,6 +2469,17 @@ const FederatedContainer = {
1270
2469
  listener = typeof listener === 'function' ? listener : listener.handleEvent;
1271
2470
  this.off(type, listener, context);
1272
2471
  },
2472
+ /**
2473
+ * Dispatch the event on this {@link Container} using the event's {@link EventBoundary}.
2474
+ *
2475
+ * The target of the event is set to `this` and the `defaultPrevented` flag is cleared before dispatch.
2476
+ * @memberof scene.Container
2477
+ * @param e - The event to dispatch.
2478
+ * @returns Whether the {@link FederatedEvent.preventDefault preventDefault}() method was not invoked.
2479
+ * @example
2480
+ * // Reuse a click event!
2481
+ * button.dispatchEvent(clickEvent);
2482
+ */
1273
2483
  dispatchEvent(e) {
1274
2484
  if (!(e instanceof FederatedEvent)) {
1275
2485
  throw new Error('Container cannot propagate events outside of the Federated Events API');
@@ -1282,6 +2492,101 @@ const FederatedContainer = {
1282
2492
  },
1283
2493
  };
1284
2494
 
2495
+ /* eslint-disable max-len */
2496
+ /**
2497
+ * PixiJS is primarily a rendering system, but it also includes support for interactivity.
2498
+ * Adding support for mouse and touch events to your project is simple and consistent.
2499
+ *
2500
+ * The new event-based system that replaced InteractionManager from v6 has expanded the definition of what a
2501
+ * Container means to be interactive. With this we have introduced `eventMode` which allows you to control
2502
+ * how an object responds to interaction events.
2503
+ * This is similar to the `interactive` property in v6 but with more options.
2504
+ *
2505
+ * <details id="enabling-interaction">
2506
+ * <summary>Enabling Interaction</summary>
2507
+ *
2508
+ * Any Container-derived object (Sprite, Container, etc.) can become interactive simply by setting its `eventMode` property to any of
2509
+ * the {@link events.EventMode} values. Doing so will cause the object to emit interaction events that can be responded to in order to drive your project's behavior.
2510
+ *
2511
+ * Check out the [interaction example code](/examples/events/click).
2512
+ *
2513
+ * Container-derived objects are based on {@link https://www.npmjs.com/package/eventemitter3|EventEmitter3}
2514
+ * so you can use `on()`, `once()`, `off()` to listen to events.
2515
+ *
2516
+ * For example to respond to clicks and taps, bind to an object ike so:
2517
+ *
2518
+ * ```javascript
2519
+ * let sprite = Sprite.from('/some/texture.png');
2520
+ *
2521
+ * sprite.eventMode = 'static'; // similar to `sprite.interactive = true` in v6
2522
+ * sprite.on('pointerdown', (event) => { alert('clicked!'); });
2523
+ * ```
2524
+ *
2525
+ * Check out the **EventTypes** section below for the full list of interaction events supported.
2526
+ * </details>
2527
+ *
2528
+ * <details id="event-modes">
2529
+ * <summary>Event Modes</summary>
2530
+ *
2531
+ * The new event-based system that replaced InteractionManager from v6 has expanded the definition of what a Container
2532
+ * means to be interactive. With this we have introduced `eventMode` which allows you to control how an object responds
2533
+ * to interaction events. This is similar to the `interactive` property in v6 but with more options.
2534
+ *
2535
+ * | event mode | Description |
2536
+ * |---|---|
2537
+ * | `none` | Ignores all interaction events, similar to CSS's `pointer-events: none`, good optimization for non-interactive children |
2538
+ * | `passive` | Does not emit events and ignores hit testing on itself but does allow for events and hit testing only its interactive children. If you want to be compatible with v6, set this as your default `eventMode` (see options in Renderer, Application, etc) |
2539
+ * | `auto` | Does not emit events and but is hit tested if parent is interactive. Same as `interactive = false` in v7 |
2540
+ * | `static` | Emit events and is hit tested. Same as `interaction = true` in v7, useful for objects like buttons that do not move. |
2541
+ * | `dynamic` | Emits events and is hit tested but will also receive mock interaction events fired from a ticker to allow for interaction when the mouse isn't moving. This is useful for elements that independently moving or animating. |
2542
+ * </details>
2543
+ *
2544
+ * <details id="event-types">
2545
+ * <summary>Event Types</summary>
2546
+ *
2547
+ * Pixi supports the following event types for interactive objects:
2548
+ *
2549
+ * | Event Type | Fired When |
2550
+ * |---|---|
2551
+ * | `pointercancel` | Pointer device button is released outside the display object
2552
+ * that initially registered a pointerdown. |
2553
+ * | `pointerdown` | Pointer device button is pressed on the display object. |
2554
+ * | `pointerenter` | Pointer device enters the display object. |
2555
+ * | `pointerleave` | Pointer device leaves the display object. |
2556
+ * | `pointermove` | Pointer device is moved while over the display object. |
2557
+ * | `globalpointermove` | Pointer device is moved, regardless of hit-testing the current object. |
2558
+ * | `pointerout` | Pointer device is moved off the display object. |
2559
+ * | `pointerover` | Pointer device is moved onto the display object. |
2560
+ * | `pointertap` | Pointer device is tapped twice on the display object. |
2561
+ * | `pointerup` | Pointer device button is released over the display object. |
2562
+ * | `pointerupoutside` | Pointer device button is released outside the display object
2563
+ * that initially registered a pointerdown. |
2564
+ * | `mousedown ` | Mouse button is pressed on the display object. |
2565
+ * | `mouseenter` | Mouse cursor enters the display object. |
2566
+ * | `mouseleave` | Mouse cursor leaves the display object. |
2567
+ * | `mousemove ` | Mouse cursor is moved while over the display object. |
2568
+ * | `globalmousemove` | Mouse is moved, regardless of hit-testing the current object. |
2569
+ * | `mouseout ` | Mouse cursor is moved off the display object. |
2570
+ * | `mouseover ` | Mouse cursor is moved onto the display object. |
2571
+ * | `mouseup ` | Mouse button is released over the display object. |
2572
+ * | `mouseupoutside ` | Mouse button is released outside the display object that initially registered a mousedown. |
2573
+ * | `click ` | Mouse button is clicked (pressed and released) over the display object. |
2574
+ * | `touchcancel ` | Touch point is removed outside of the display object that initially registered a touchstart. |
2575
+ * | `touchend ` | Touch point is removed from the display object. |
2576
+ * | `touchendoutside ` | Touch point is removed outside of the display object that initially registered a touchstart. |
2577
+ * | `touchmove ` | Touch point is moved along the display object. |
2578
+ * | `globaltouchmove` | Touch point is moved, regardless of hit-testing the current object. |
2579
+ * | `touchstart ` | Touch point is placed on the display object. |
2580
+ * | `tap ` | Touch point is tapped twice on the display object. |
2581
+ * | `wheel ` | Mouse wheel is spun over the display object. |
2582
+ * | `rightclick ` | Right mouse button is clicked (pressed and released) over the display object. |
2583
+ * | `rightdown ` | Right mouse button is pressed on the display object. |
2584
+ * | `rightup ` | Right mouse button is released over the display object. |
2585
+ * | `rightupoutside ` | Right mouse button is released outside the display object that initially registered a rightdown. |
2586
+ * </details>
2587
+ * @namespace events
2588
+ */
2589
+ /* eslint-enable max-len */
1285
2590
  const init = () => {
1286
2591
  extensions.add(EventSystem);
1287
2592
  extensions.mixin(Container, FederatedContainer);