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.
Note: this browser doesn't expose
rawgamepadinputchange. Enable chrome://flags/#enable-experimental-web-platform-features or run Chrome 149+ to see the event row populated. The poll row will still work.
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
- Gamepad Event-Driven Input API — feature index
- Latency Comparator — average interval comparison
- ChromeStatus entry
- Gamepad spec
implementation reference
Need the exact API surface, compatibility boundaries, errors, lifecycle, and source links? Read the matching gendn reference ↗