Adding Input Handling to a Scene

Scenes do not have event listeners attached by default. To initialize the event system (that will attach and set up listeners), call scene.initializeEvents().

Accessibility related input listeners require a timer to work with assistive devices and to keep track of the state of the keyboard. In order for accessibility input to work correctly, call axon.timer.emit( timeElapsedInSeconds ) prior to each call to display.updateDisplay(). display.updateOnRequestAnimationFrame() will do this for you. Take a look at Accessibility in Scenery for more information about accessibility.

Pointers

A pointer is an abstract way of describing a mouse, a single touch point, or a pen/stylus, similar to in the Pointer Events specification. Touch and pen pointers are transient, created when the relevant DOM down event occurs and released when corresponding the DOM up or cancel event occurs. However, the mouse pointer is persistent.

Input event listeners can be added to nodes directly, or to a pointer or the Display. When a DOM event is received, it is first broken up into multiple events (if necessary, e.g. multiple touch points), then the dispatch is handled for each individual Scenery event. Events are first fired for any listeners attached to the pointer that caused the event, then fire on the node directly under the pointer, and if applicable, bubble up the graph to the Scene from which the event was triggered. Finally, listeners attached to the Display will be triggered. Events are not fired directly on nodes that are not under the pointer at the time of the event..

Listeners and Events

Event listeners are added with node.addInputListener( listener ), pointer.addInputListener( listener ) and display.addInputListener( listener ). This listener can be an arbitrary object, and the listener will be triggered by calling listener[eventType]( event ), where eventType is one of the event types as described below, and event is a Scenery event with the following properties:

trail A Trail pointing to the node under the pointer.
pointer The Pointer that triggered the event. Additional information about the mouse/touch/pen can be obtained from the pointer, for example event.pointer.point.
type The base type of the event (e.g. for touch down events, it will always just be "down").
domEvent The underlying DOM event that triggered this Scenery event. The DOM event may correspond to multiple Scenery events, particularly for touch events. This could be a TouchEvent, PointerEvent, MouseEvent, MSPointerEvent, etc.
target The leaf-most Node in the Trail.
currentTarget The Node to which the listener being fired is attached, or null if the listener is being fired directly from a pointer.

Event Types

Scenery will fire the following base event types:

down Triggered when a pointer is pressed down. Touch / pen pointers are created for each down event, and are active until an up/cancel event is sent.
up Triggered when a pointer is released normally. Touch / pen pointers will not have any more events associated with them after an up event.
cancel Triggered when a pointer is canceled abnormally. Touch / pen pointers will not have any more events associated with them after an up event.
move Triggered when a pointer moves.
wheel Triggered when the (mouse) wheel is scrolled. The associated pointer will have wheelDelta information.
enter Triggered when a pointer moves over a Node or one of its children. Does not bubble up. Mirrors behavior from the DOM mouseenter.
exit Triggered when a pointer moves out from over a Node or one of its children. Does not bubble up. Mirrors behavior from the DOM mouseleave.
over Triggered when a pointer moves over a Node (not including its children). Mirrors behavior from the DOM mouseover.
out Triggered when a pointer moves out from over a Node (not including its children). Mirrors behavior from the DOM mouseout.
keydown Triggered when a key is pressed down. Fires on the keyboard-focused node and bubbles down.
keydown Triggered when a key is released. Fires on the keyboard-focused node and bubbles down.

Before firing the base event type (for example, move), Scenery will also fire an event specific to the type of pointer. For mice, it will fire mousemove, for touch events it will fire touchmove, and for pen events it will fire penmove. Similarly, for any type of event, it will first fire pointerType+eventType, and then eventType.

Event Dispatch

SceneryEvents have two methods that will cause early termination: event.abort() will cause no more listeners to be notified for this event, and event.handle() will allow the current level of listeners to be notified (all pointer listeners, or all listeners attached to the current node), but no more listeners after that level will fire. handle and abort are like stopPropagation, stopImmediatePropagation for DOM events, except they do not trigger those DOM methods on the underlying DOM event.

Up/down/cancel events all happen separately, but for move events, a specific sequence of events occurs if the pointer changes the node it is over:

  1. The move event is fired (and bubbles).
  2. An out event is fired for the old topmost Node (and bubbles).
  3. exit events are fired for all Nodes in the Trail hierarchy that are now not under the pointer, from the leaf-most to the root-most. Does not bubble.
  4. enter events are fired for all Nodes in the Trail hierarchy that were not under the pointer (but now are), from the root-most to the leaf-most. Does not bubble.
  5. An over event is fired for the new topmost Node (and bubbles).

event.abort() and event.handle() will currently not affect other stages in the 'move' sequence (e.g. event.abort() in the 'move' event will not affect the following 'out' event).

For each event type:

  1. Listeners on the pointer will be triggered first (in the order they were added)
  2. Listeners on the target (top-most) Node will be triggered (in the order they were added to that Node)
  3. Then if the event bubbles, each Node in the Trail will be triggered, starting from the Node under the top-most (that just had listeners triggered) and all the way down to the Scene. Listeners are triggered in the order they were added for each Node.
  4. Listeners on the display will be triggered (in the order they were added)

For each listener being notified, it will fire the more specific pointerType+eventType first (e.g. 'mousemove'), then eventType next (e.g. 'move').

Currently, preventDefault() is called on the associated DOM event if the top-most node has the 'interactive' property set to a truthy value.

Relevant Specifications