Play when it scrolls into view: a chart
A chart that waits until the reader actually sees it, then draws itself, and does it again the next time it comes back into view. The sample comp is Stats chart (folder Interactive examples).
Loading the player…
Try it: scroll the chart out of view and back. A click on it replays the reveal.
How it works
A state machine cannot tell whether its canvas is on screen. The page can: the browser's IntersectionObserver reports when an element enters or leaves the viewport. So the work is split:
- The file has two states. waiting parks on the first frame (the empty chart) and reveal plays the bars once and holds the last frame. Event
showgoes from waiting to reveal, eventhideback. - The page fires
showwhen most of the canvas is visible andhidewhen it is gone.
| State | Plays | Leaves on |
|---|---|---|
| waiting | the first frame of reveal, held (Set frame 0 on entering) | show |
| reveal | reveal, 0–59, once; holds the last frame | hide |
Why Set frame 0 on waiting. A state that does not play keeps whatever frame it was entered on. Without it, hide would leave the finished chart up, and the next show would start from the middle.
The motion follows the content: faint grid lines fade in first, the bars grow from the baseline one after another (4 frames apart, ease-out) while the total counts up (3.1k → 6.8k → 9.9k → 12.4k, swapped on hold keys), a trend line draws itself through the bar tops with a dot popping at each, and the trend chip settles last. Each frame of the reveal is a sensible still, so a reader who scrolls past quickly sees a partly drawn chart, never a broken one.
A click replays it: Click → Fire hide, Fire show. The machine checks its rules after each action, so the two fires in a row go to waiting and straight back to reveal.
In After Effects
- One marker,
reveal(0–59): the chart from empty to full. Frame 0 is the empty chart. - Build as
.lottiewith a state machine: two states, two events, as in the table.
On a web page
js
// the version these pages use
import { DotLottie } from "https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web@0.81.0/+esm";
const canvas = document.querySelector("#chart");
const chart = new DotLottie({ canvas, src: "stats-chart.lottie" });
chart.addEventListener("load", () => {
chart.stateMachineLoad("visible");
chart.stateMachineStart();
let shown = false;
new IntersectionObserver(([entry]) => {
const now = entry.intersectionRatio >= 0.6; // most of it on screen
if (now === shown) return;
shown = now;
chart.stateMachineFireEvent(now ? "show" : "hide");
}, { threshold: [0, 0.6] }).observe(canvas);
});To play it only the first time, disconnect the observer after the first show (or leave out the hide rule in the file).
Variations
- A counter or a progress ring on a landing page that fills when it is reached.
- An illustration that greets the reader at the top of a section.
- Pause what is not visible: fire
hideinto a looping animation's machine to park it while it is off screen.