addmotion
Submit Free API key

Data story — KPI count-up + chart

A headline number counts up, a line chart draws behind it, and two supporting stats land — perfect for investor updates and growth posts.

Prompt

# Data story — KPI count-up + chart

## Format (read first)
- 1920×1080 (16:9), 30fps, 8.0s = 240 frames
- Target: Single HTML file

## Brief
A data story (8s) for Ledgerly. The data must be accurate to the series given: 12, 15, 14, 21, 26, 31, 38, 48. Calm, credible, no 3D charts.

## Look
- Palette (background, accent, text): #f4efe6, #1f6f5c, #1d1c1a
- Type: Sans with tabular numerals. Value 200px/850; labels 28px/600 uppercase, letter-spacing 0.12em.

## Beats (exact timings)
1. 0.0–0.8s — Label "Monthly revenue" fades up top-left.
2. 0.8–3.2s — The value counts from 0 to $48,200 with ease-out-quart (format with the same separators and currency as the final value). Simultaneously the line chart of the series draws left→right behind it at 20% opacity.
3. 3.2–4.4s — The last data point gets an accent dot that pulses once (scale 1→1.6→1). Area under the line fades to 12%.
4. 4.4–6.4s — Two stat chips "+212% YoY" and "3,400 customers" slide up from the bottom with 120ms stagger.
5. 6.4–8.0s — "Ledgerly" logo bottom-right. Hold.

## Motion rules
- Count-up and line draw must finish on the same frame.
- Chart y-axis starts at 0 unless told otherwise — no misleading scales.

## Known failure modes — avoid these
- Number width jitter during count-up — use font-variant-numeric: tabular-nums.

## Build
- Output ONE self-contained HTML file. No CDNs, web fonts, images or scripts from URLs.
- The stage is exactly 1920×1080 and scales to fit the window (letterbox) while keeping the aspect ratio.
- Expose window.__addmotion = { width: 1920, height: 1080, fps: 30, duration: 8, seek(t) } where seek(t) renders the exact frame for time t in seconds.
- Make every frame a pure function of t: compute positions from t (with easing functions you define) rather than accumulating state. Use requestAnimationFrame only to call seek(performance.now()/1000 % duration) for live preview.
- If you use CSS @keyframes, seek(t) must set animation-play-state: paused and a negative animation-delay of -t seconds on every animated element.
- To export MP4, step seek(t) frame by frame in a headless browser, screenshot each frame, and encode with ffmpeg.

## Done when
- [ ] Final value exactly matches the input
- [ ] Chart shape matches the series
- [ ] You scrubbed the start, middle and end of every beat and nothing overlaps, clips or jumps

Before writing code, restate the beat list with frame numbers. Then build it in one pass.

More like this

16:9

Bar chart grow-in

Data & charts · Dataframe (demo)
16:9

Line chart trace

Data & charts · Dataframe (demo)
16:9

Odometer counter

Data & charts · Dataframe (demo)
16:9

Donut progress ring

Data & charts · Dataframe (demo)
Data story — KPI count-up + chart · addmotion