Skip to content

PressListener and FireListener

PressListener and FireListener (both from scenerystack/scenery) are the input listeners that give a Node press/click behavior. PressListener is the general-purpose base — it tracks whether a pointer is pressed/hovering/focused and exposes press/release/drag callbacks — and is also the shared base class for DragListener. FireListener adds one thing on top: a fire() callback invoked on a complete press-then-release (or on down, if fireOnDown is set), which is exactly the "button" interaction pattern. Attach either as an inputListeners entry on a Node, and make sure the owning Display has called initializeEvents().

ts
import { Circle, FireListener } from 'scenerystack/scenery';
import { Tandem } from 'scenerystack/tandem';

const button = new Circle( 25, {
  fill: 'dodgerblue',
  cursor: 'pointer'
} );

button.addInputListener( new FireListener( {
  fire: () => console.log( 'fired!' ),
  tandem: Tandem.REQUIRED
} ) );

FireListener options

FireListenerOptions adds these to everything PressListener accepts:

OptionDefaultEffect
fireno-opCalled as fire( event ) when the button fires
fireOnDownfalseIf true, fires on press instead of on release-while-hovering
fireOnHoldfalseEnables fire-on-hold (repeated firing while held)
fireOnHoldDelay400Milliseconds held before fire-on-hold starts repeating
fireOnHoldInterval100Milliseconds between repeated fires once fire-on-hold is active

PressListener options

OptionDefaultEffect
pressno-opCalled as press( event, listener ) when a press starts
releaseno-opCalled as release( event | null, listener ) when released, interrupted, or canceled
dragno-opCalled as drag( event, listener ) on pointer move while pressed
targetNodenullOverrides the Node used to compute the pressed Trail/coordinate frame, when it differs from the Node the listener is attached to
attachtrueWhether this listener attaches itself to the pointer (blocking other attach: true listeners while pressed)
mouseButton0 (left)Restricts which mouse button starts a press; any touch/pen still works
pressCursor'pointer'Cursor to force while pressed
canStartPressalways truePredicate checked before allowing a press to start
collapseDragEventsfalseCoalesces multiple drag events between frames into one drag() call

Useful read-only properties

PropertyMeaning
isPressedPropertyWhether the listener is currently pressed
isOverPropertyWhether a pointer is currently over the associated Node
isHoveringPropertytrue while a pointer that could fire this listener is over it (pressed-and-over, or unpressed-and-over)
isHighlightedProperty`isPressed
pointer / pressedTrailThe active Pointer and press Trail, or null when not pressed
interruptedWhether the most recent release was due to an interruption rather than a normal up/click

Methods shared by both

MethodEffect
press( event, targetNode?, callback? )Programmatically attempts to start a press; returns whether it succeeded
release( event?, callback? )Programmatically ends the press
interrupt()Cancels an in-progress press without treating it as a normal release (no fire() on FireListener)
dispose()Releases the listener's Property/Emitter resources

FireListener additionally exposes fire( event ) (invoke the fire callback directly) and click( event, callback? ) (used by PDOM/accessibility interactions to press-and-release in one step).

Use FireListener for buttons, PressListener/DragListener for everything else

If you just need "clicked," reach for FireListener — it already integrates with keyboard/PDOM activation. If you need to track pointer movement while pressed (dragging a Node around), use PressListener directly or DragListener, which builds on the same press/release/drag shape.

tandem defaults to required

Both listeners default tandem to Tandem.REQUIRED (for PhET-iO instrumentation of user actions). If your project isn't PhET-iO-instrumented, pass Tandem.OPT_OUT, or supply a real tandem as shown above — leaving the default in place will throw if PhET-iO validation is active.