PTENES
MODULE 3.2

🌍 World Population Shift (D3)

Documentary-style animation of population growth by country, 1990–2030. Without D3: you have numbers. With D3: you have a story that unfolds in real time before the viewer.

6
Sections
~45
min
D3
Lib
40
Years of data
1

📊 Scenario: Data That Wants to Be a Story

You have a spreadsheet: country, year, population. They’re just numbers until D3 turns them into bars that grow, change position, and reveal four decades of geopolitical drama. The viewer doesn’t read the table — they watch it happen.

Why D3 for this project?

D3 is the only library in the stack with native scales (linear, band, time) and data transition management. You don’t calculate pixels manually—you define the domain and range, and D3 handles the geometry. GSAP would animate the visuals, but it wouldn’t understand the data.

✓ D3 is ideal when…

Dataset that changes over time
Axes, rankings, and automatic scales
Reuse with different datasets

✗ D3 isn’t the best choice when…

Storytelling without data (→ GSAP)
3D scenes (→ Three.js)
App micro-animations (→ Lottie)
scaleLinear
automatic pixels
scaleBand
bar positions
sort
dynamic ranking
interpolate
smooth transition
2

🏃 Bar Race: the heart of the project

On each Remotion frame, the dataset for the corresponding year is read, the bars are reordered, and the Y positions are smoothly interpolated. When China and India switch places, the bar race pause for 12 frames — the dramatic moment.

bar race — live demo
2015
1 China
1.41B
2 India
1.43B
3 USA
335M
4 Indonesia
277M
5 Pakistan
231M

💡 The dramatic pause

When a change in leadership occurs, add 12 frames pause before reordering. It's the cinematic equivalent of a close-up — it gives the viewer time to process what just happened.

Dynamic sort
every frame
12f pause
change of leader
Interpolation
smooth Y position
Drama
visual tension
3

📐 D3 Scales in the Remotion Context

The D3+Remotion integration works because D3 calculates geometry and Remotion advances time. With each call to useCurrentFrame(), you compute the corresponding data frame and let D3 map the pixels.

D3 + Remotion integration pattern
const frame = useCurrentFrame();
const fps = useVideoConfig().fps;
const year = Math.floor(interpolate(frame, [0, durationInFrames], [1990, 2030]));

const data = getDataForYear(year);
const xScale = scaleLinear().domain([0, maxPop]).range([0, width]);
const yScale = scaleBand().domain(data.map(d => d.country)).range([0, height]);
useCurrentFrame frame → year Dataset getDataForYear() D3 scales domain → range Sort + Rank Y position SVG bars render frame Deterministic pipeline — the same frame always produces the same result
Deterministic
Same frame = same result
Domain
[0, maxPopulation]
Range
[0, width]
No state
Pure calculation
4

🏷️ Labels, Year, and Readability in Motion

Labels follow the bars; the year counter in the lower-right corner anchors viewers in time. Both need to be calculated in the same frame — without separate state.

✓ Labeling best practices

Label positioned at X = bar width + 6px
Formatted value: "1.4B," not "1,410,000,000"
Label color = bar color, alpha 0.9

✗ Common mistakes

Fixed axis label — gets left behind as the bar grows
Full number—illegible in fast motion
One color for everyone — loses each country's identity

💡 Year counter as an anchor

The large year in the corner is the viewer’s compass. Minimum size: 64px, opacity 0.5–0.7 so it doesn’t compete with the bars. Use font-variant-numeric: tabular-nums to prevent the digits from “jumping” when changing.

Follow label
x = bar.width + 6
Format "1.4B"
legible in motion
tabular-nums
without digit jumps
Color by country
persistent identity
5

💬 The Complete Prompt

This is the exact prompt you give Claude Code. Each instruction maps to a specific bar race behavior — Claude generates the Remotion composition with D3 integrated in one response.

prompt — copy and use
Create an animated bar race showing the ten most populous
countries from 1990 to 2030.
Animate transitions smoothly.
Display ranking changes in real time.
Pause briefly when leadership changes.

💡 Why "Pause briefly when leadership changes"?

This specific instruction makes Claude implement the dramatic pause. Without it, the reordering happens continuously and goes unnoticed. With it, the viewer gets the cinematic moment of “wait, India passed China!”

"bar race"
recognized pattern
"smoothly"
smooth transitions
"real time"
synchronized labels
"pause"
explicit drama
6

♻️ Deliverables and Reusability

The deliverable is a YouTube-style infographic video—but the component is a parameterized template that works with any time-based ranking dataset. Swap the spreadsheet, change the title, render another video.

Build order: from spreadsheet to video

1

Prepare the dataset

JSON array of objects {country, year, population}. Data for 1990, 2000, 2010, 2020, 2030. Interpolate the years in between.

2

Build scales and stills

Validate that the bars appear at the correct size without animation. Confirm that the 1990 ranking is correct.

3

Connect the frame to time

Use interpolate() to map frame → year. Add a pause for years when leadership changes.

4

Polish: colors, typography, music

Add a visual identity for each country, a bold font for the numbers, and dramatic music (Track 4).

YouTube
viral infographic
Finance
revenue ranking
Sports
points table
Policy
presidential approval

📋 Module 3.2 Summary

← SaaS Walkthrough Next: Motorcycle Commercial →