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.