Skip to content

KeyboardDragListener

KeyboardDragListener (from scenerystack/scenery) is a KeyboardListener specialized for dragging: it moves an object with the arrow keys or W/A/S/D, writing to the same kind of model positionProperty a pointer DragListener would. Pointer dragging alone is never accessible, so any draggable object that needs to work for keyboard/switch users needs this listener (or RichDragListener, which bundles both) in addition to — or instead of — pointer dragging.

ts
import { Node, KeyboardDragListener } from 'scenerystack/scenery';

const bodyNode = new Node( { tagName: 'div', focusable: true } );

bodyNode.addInputListener( new KeyboardDragListener( {
  positionProperty: body.positionProperty,
  transform: modelViewTransform,
  dragBoundsProperty: model.dragBoundsProperty,
  dragSpeed: 150,     // model units/second while a key is held
  shiftDragSpeed: 50  // finer motion with shift held
} ) );

Options

KeyboardDragListenerOptions accepts everything DragListener shares via AllDragListenerOptions (positionProperty, transform, dragBoundsProperty, mapPosition, translateNode, start/drag/end), plus:

OptionDefaultEffect
dragDelta10Discrete step (in parent/view coordinates) moved per moveOnHoldInterval tick — a "typical application" feel; mutually exclusive with dragSpeed/shiftDragSpeed
shiftDragDelta5Finer dragDelta while shift is held
dragSpeed0Continuous units/second moved while a direction key is held — smoother, game-like motion; mutually exclusive with dragDelta/shiftDragDelta
shiftDragSpeed0Finer dragSpeed while shift is held
keyboardDragDirection'both'Constrains motion: 'both' (2D), 'leftRight', or 'upDown'
moveOnHoldDelay500Milliseconds a key must be held before repeat movement begins (delta mode only)
moveOnHoldInterval400Milliseconds between discrete steps once repeating (delta mode only; must be > 0)

dragSpeed/shiftDragSpeed and dragDelta/shiftDragDelta are mutually exclusive — pick one motion model per listener. If you pass dragBoundsProperty, you must also provide positionProperty or translateNode: true, since the listener otherwise has no way to know the current position to constrain.

Public state

MemberMeaning
modelDeltaThe Vector2 delta (in model coordinates) applied during the current drag step
modelPointThe current drag point in model coordinates
isPressedProperty (inherited from KeyboardListener)Whether a drag is currently active

Methods

Shares interrupt() and dispose() with KeyboardListener, since KeyboardDragListener extends it directly.

Requires a focusable target — pair it with the PDOM

KeyboardDragListener only receives key events when its Node has keyboard focus. Set tagName: 'div' and focusable: true (and a meaningful accessibleName) on the target Node, or the listener will never fire. See Drag Listeners for the full checklist, including combining this with pointer dragging via RichDragListener.