demo · v149

Button Timeline

Press buttons on a gamepad. Each input is rendered as a tick on two timelines — top: every rawgamepadinputchange event, bottom: every value seen during a 60Hz rAF poll. Quick taps that happen between frames show up as event ticks but get swallowed by the poll.

no gamepad detected — press any button to connect
rawgamepadinputchange (event-driven) navigator.getGamepads() (rAF polled)
EVENT row0 ticks
POLL row0 ticks
events captured
polls hit a new value
events missed by poll

code

// event-driven row (Chrome 149)
window.addEventListener('rawgamepadinputchange', (e) => {
  draw(eventCanvas, performance.now(), e.gamepad.buttons[0].pressed);
});

// polled row (compat)
function loop() {
  const pads = navigator.getGamepads();
  if (pads[0]) draw(pollCanvas, performance.now(), pads[0].buttons[0].pressed);
  requestAnimationFrame(loop);
}
loop();

The same physical button can fire twice per frame at high rates — for example a rapid trigger half-pull on a sim wheel. The event row catches both edges. The poll row only ever sees the last value at the moment the frame samples.

see also

implementation reference

Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗