Animate a stock chart with real data
A scrubbing-line stock chart from a JSON of price points. The windowing trick, the easing, and the render.
An animated stock chart is one of those things that looks intimidating until you build one. The data is a 1-D array of prices. The chart is an SVG <polyline>. The animation is stroke-dashoffset. There are four lines of math.
Here is the version, with a real-data shape and the windowing trick that keeps long time-series readable.
The data
Flat JSON, one point per time-step:
{
"ticker": "EXAMPLE",
"points": [
{ "t": "2026-04-01", "p": 142.30 },
{ "t": "2026-04-02", "p": 144.15 },
{ "t": "2026-04-03", "p": 140.95 }
// ... 60 more
]
}Sort by t ascending. Compute min and max for the y-axis. The rest is layout.
The SVG
<svg viewBox="0 0 800 300" preserveAspectRatio="none">
<polyline id="line" fill="none" stroke="#ff3b1f" stroke-width="2"
points="0,250 50,220 100,240 150,180 200,160 ..." />
</svg>Compute the points from data:
function build(points, w, h) {
const ps = points.map(d => d.p);
const lo = Math.min(...ps), hi = Math.max(...ps), range = hi - lo;
return points.map((d, i) => {
const x = (i / (points.length - 1)) * w;
const y = h - ((d.p - lo) / range) * h;
return `${x},${y}`;
}).join(' ');
}That is the whole chart. Everything else is decoration.
The reveal animation
The classic SVG trick: animate stroke-dasharray and stroke-dashoffset so the line draws itself left to right.
const line = document.getElementById('line');
const len = line.getTotalLength();
line.style.strokeDasharray = len;
line.style.strokeDashoffset = len;
line.style.transition = 'stroke-dashoffset 2s cubic-bezier(.16, 1, .3, 1)';
requestAnimationFrame(() => { line.style.strokeDashoffset = 0; });getTotalLength() returns the polyline's path length in user units. Setting stroke-dasharray to that length and offsetting by the same amount hides the entire line. Animating the offset to 0 reveals it.
For deterministic rendering, drive the dashoffset as a function of t instead of with a CSS transition:
addEventListener('hf-seek', e => {
const u = Math.min(1, e.detail.time / 2);
const ease = 1 - Math.pow(1 - u, 3);
line.style.strokeDashoffset = len * (1 - ease);
});The windowing trick
The hardest part of long time-series: 252 trading days at 4px each is over 1000px wide. On a 16:9 canvas, the early data points are unreadable.
The fix: window the data. Show 20-40 points at a time. As time advances, the window slides right; old points scroll off-screen.
function renderWindow(allPoints, t, windowSize, totalDuration) {
const progress = t / totalDuration;
const start = Math.floor(progress * (allPoints.length - windowSize));
return allPoints.slice(start, start + windowSize);
}The eye reads this as a zooming through time chart. Much more legible than the static-frame version.
The endpoint flash
A small detail that elevates the chart: a pulsing dot on the most recent data point. The eye is drawn to motion; the pulse says "this is where you are."
<circle id="head" r="6" fill="#ff3b1f">
<animate attributeName="r" values="6;10;6" dur="1.5s" repeatCount="indefinite" />
<animate attributeName="opacity" values="1;0.4;1" dur="1.5s" repeatCount="indefinite" />
</circle>Update cx and cy on every frame to track the last drawn point. The pulse is purely decorative — it carries no data — but it gives the chart life.
The complete picture
{
"ticker": "EXAMPLE",
"points": [
{ "t": "2026-04-01", "p": 142.30 },
{ "t": "2026-04-02", "p": 144.15 },
{ "t": "2026-04-03", "p": 140.95 },
{ "t": "2026-04-04", "p": 146.20 },
{ "t": "2026-04-05", "p": 151.05 },
{ "t": "2026-04-08", "p": 149.80 },
{ "t": "2026-04-09", "p": 153.40 },
{ "t": "2026-04-10", "p": 158.25 }
]
}When to render to MP4
A chart as a static image is useful. A chart as an MP4 is more useful in three specific cases:
- Social media — a 6-second animated price chart gets dramatically more attention than a screenshot.
- Earnings calls — embedded in slides, the chart draws itself in front of the audience.
- Newsletters — modern email clients support MP4 inline; an animated chart in a financial newsletter reads as broadcast-quality.
For all three, the render pipeline takes the JSON + template and returns an MP4. See the live bar chart tutorial for the simpler data shape and pattern.
The version with real data
If you wire this to a real data feed:
- Polygon, Alpaca, or Finnhub for equities. Free tiers cover ~5 calls/minute, enough for daily renders.
- CoinGecko for crypto. Generous free tier.
- Your own database if the data is internal (revenue, user counts, etc.).
The render is the cheap part. The data layer is where most of the time goes. Once you have a reliable feed, the chart is a build artifact — same input, same output, every time. See the developer overview for the full SDK surface.
A stock chart with motion is the kind of widget that used to be reserved for Bloomberg terminals. Now it is forty lines of SVG and a JSON file. The asymmetry is the entire point.
Cite this postBibTeX · APA · Markdown
@misc{tanaka2026animate,
author = {Kira Tanaka},
title = {Animate a stock chart with real data},
year = {2026},
url = {https://hyperframes.video/blog/stock-chart-animation},
note = {HyperFrames blog}
}Kira Tanaka. (2026, May 8). Animate a stock chart with real data. HyperFrames. https://hyperframes.video/blog/stock-chart-animation
[Animate a stock chart with real data](https://hyperframes.video/blog/stock-chart-animation) — Kira Tanaka, 2026
Kira works on the render core: headless Chromium scheduling, frame capture, and the encoder pipeline. She cares about reproducible builds and small numbers next to the word "variance."
Animated poll results as MP4
Build a poll results animation that renders to deterministic MP4: four horizontal bars race to their final percentages, then a winner ribbon sweeps in.
Animated flight itinerary cards in HTML
Build an animated boarding pass video: a plane traces an arc from origin to destination, gate and time settle in, the pass folds out — rendered as MP4.
Animated fitness summary cards (Strava-style recaps)
Build a fitness recap video generator: distance, pace, and elevation tick up, a route map traces itself, and weekly streak dots fill in — exported as MP4.
Building with HyperFrames? Come hang out.
We're on GitHub, in Discord, and the playground is one click away. Bring weird ideas — we collect them.