Command Palette

Search for a command to run...

Hectal
Back to the lesson: Topic 9.5 — The Animation Loop and Reduced Motion
Data Visualization · Example 2 of 2

One function, two paths: jump or slide, and stop when hidden

On your own computer the first line of the real code reads your setting. Switch it in your system's accessibility settings (or in the browser's developer tools, under Rendering, "Emulate CSS media feature prefers-reduced-motion") and run the page again.

Everything that moves on a web page is drawn in frames. requestAnimationFrame and d3.timer call your function once per frame, and your function should place things by elapsed time, not by counting frames. Respect prefers-reduced-motion, and stop loops when the page is hidden.

Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.

Ready for more? This phase has 4 hands-on exercises with automatic checks.

Practice questions

Write the code in the editor, run it, then open the model answer to compare.

01

Write animate(duration, draw) with d3.timer: it calls draw(k) with k from 0 to 1 by elapsed time, stops itself at 1 and returns a promise. Why is a promise useful here?

02

Write motion(ms) that returns 0 when reduced motion is requested and ms otherwise, and use it in bar.transition().duration(motion(300)). What happens with a duration of 0?

Explain it without notes

01

Why should an animation be placed by elapsed time and not by counting frames?

02

What is the difference between requestAnimationFrame and setInterval(fn, 16)?

03

What does prefers-reduced-motion: reduce mean, and what should a chart do about it?

One function, two paths: jump or slide, and stop when hidden

Preview

Press Run to see the page.

Console

Nothing logged yet.

Expected console output

the setting is read with: (prefers-reduced-motion: reduce) | matches is a boolean
reduced = true:  jumped to 200 | attribute right away: 200
reduced = false: slid to 200
a change of the setting while the page is open is heard with query.addEventListener('change', fn): function
frames while visible > 0: true
hidden: loop stopped
frames added while hidden: 0
visible: loop started
frames added after coming back > 0: true