Events
The event system delivers a synthetic SceneEvent to node listeners. Native
Pointer/Wheel events are normalized, hit-tested, and dispatched DOM-style
(capture → target → bubble). The event carries the pointer position in both screen and
world space.
SceneEvent
Section titled “SceneEvent”The object every listener receives. type SceneEventListener = (event: SceneEvent) => void.
Properties
Section titled “Properties”| Property | Type | Description |
|---|---|---|
type |
SceneEventType |
The event name. |
target |
Node |
The node the interaction resolved to. Constant. |
currentTarget |
Node |
The node currently handling the event. Updated as it propagates. |
eventPhase |
SceneEventPhase |
The current propagation phase. |
screenPoint |
Vec2 |
Pointer position in screen space. |
worldPoint |
Vec2 |
Pointer position in world space. |
nativeEvent |
Event | null |
The originating native Pointer/Wheel event; null for synthetic events. |
bubbles |
boolean |
Whether the event bubbles. Default true; false for pointerenter/pointerleave. |
pointerId |
number |
Pointer id. -1 when not applicable. |
button |
number |
The button that changed. -1 when not applicable. |
buttons |
number |
Bitmask of buttons currently held. |
deltaX |
number |
Wheel delta X. 0 when not applicable. |
deltaY |
number |
Wheel delta Y. 0 when not applicable. |
altKey / ctrlKey / shiftKey / metaKey |
boolean |
Modifier flags, snapshotted from the native event (false for synthetic events). |
Methods
Section titled “Methods”| Method | Description |
|---|---|
stopPropagation(): void |
Halt the walk after the current node. |
stopImmediatePropagation(): void |
Also stop the remaining listeners on the current node. |
preventDefault(): void |
Set defaultPrevented and forward to the native event (e.g. stop page scroll on wheel). |
getLocalPoint(node?: Node): Vec2 |
Map worldPoint into a node’s local space (defaults to currentTarget); computed lazily. |
interface SceneEventInit is the constructor input for new SceneEvent({ … }).
shape.on('click', (e) => { console.log(e.type, e.target.type, e.getLocalPoint()) if (e.altKey) e.stopPropagation()})SceneEventType
Section titled “SceneEventType”The 11 supported event names:
| Group | Names |
|---|---|
| Pointer | pointerdown, pointerup, pointermove |
| Hover | pointerenter, pointerleave |
| Click | click, dblclick |
| Wheel | wheel |
| Drag | dragstart, dragmove, dragend |
SceneEventPhase
Section titled “SceneEventPhase”type SceneEventPhase = 'capture' | 'target' | 'bubble'EventManager
Section titled “EventManager”The glue between the browser and the scene graph. Created and owned by the Stage — you
rarely construct it directly.
class EventManager { constructor(stage: Stage) bind(): void // attach native Pointer/Wheel listeners on the stage container destroy(): void // unbind every native listener}For each native event the manager: computes the screen point
(clientX/Y − container.getBoundingClientRect()), converts to world via
stage.screenToWorld, resolves the target via stage.getIntersection (or the stage if
nothing is hit), builds a SceneEvent, and calls dispatchEvent.
It also runs the state machines that derive the high-level events:
- click —
pointerupwhose target equals thepointerdowntarget (and no drag occurred). - dblclick — two clicks on the same target within
300 ms. - drag — once the pointer moves more than
3 pxfrom the press point, firesdragstart, thendragmove, thendragendon release. Drag events target the press node. - hover — when the current hit changes, fires
pointerleaveon the old node andpointerenteron the new (non-bubbling, but capture-traversed).
The wheel listener is bound with { passive: false }, so a handler calling
preventDefault() can stop page scroll (used for zoom).
dispatchEvent
Section titled “dispatchEvent”The pure capture → target → bubble walk (no DOM dependency). Also exported for advanced use and testing.
function dispatchEvent(event: SceneEvent, path: readonly Node[]): voidpath is ordered target-first: [target, parent, …, root]. The walk:
- capture — root down to the target’s parent (capture listeners).
- target — the target’s capture listeners, then its bubble listeners.
- bubble — the target’s parent up to the root (bubble listeners) — only if
event.bubbles.
stopPropagation() halts after the current node; stopImmediatePropagation() additionally
stops the remaining listeners on that node. Non-bubbling events
(pointerenter/pointerleave) still traverse capture and target — so ancestor capture
listeners can observe descendant hover.
const path = [leaf, mid, root] // target-firstdispatchEvent(new SceneEvent({ type: 'click', target: leaf, /* … */ }), path)// → root capture, mid capture, leaf (capture+bubble), mid bubble, root bubble