К основному содержанию
скилл CX Codex

chart-animation — скилл для Claude Code: что делает и как установить

Скилл учит ИИ анимировать графики и гонки столбцов через Remotion и D3. Помогает переносить данные из CSV в детерминированное видео без рассинхронизации кадров.

Установить в Claude Code · Через Skills CLI (Vercel) Все способы и платформы ↓
npx skills add iart-ai/data-animation-skills --skill chart-animation -a claude-code
Открыть на GitHub

Что делает chart-animation

Скилл даёт правила для сборки анимированной инфографики: гонок столбцов (bar chart race), счётчиков чисел и графиков с плавным появлением линий. Главный принцип здесь — детерминированный рендер. Значения рассчитываются строго от номера текущего кадра через useCurrentFrame() в Remotion, а не от системных часов операционной системы.

Сторонние анимационные таймеры в Chart.js, GSAP или D3 вызывают мерцание и рассинхрон при покадровой сборке видео, поэтому их обязательно отключают. Библиотека D3 используется только для шкал и геометрии (scaleLinear, scaleBand). Числа форматируются через Intl.NumberFormat с предварительным округлением и CSS-стилем tabular-nums, чтобы ширина цифр оставалась одинаковой и верстка не дёргалась.

Инструкции задают тайминги показа: пауза 1–1.5 секунды на старте для чтения осей, от 0.3 до 0.6 секунды на строку данных и финальная задержка на 2–3 секунды для сохранения понятного итога. Шаблон компонента полностью отделён от данных, поэтому один подготовленный макет можно пакетом отрендерить через Remotion CLI сразу для пачки файлов CSV.

Какие задачи решает

  • анимировать гонку столбцов (bar chart race) по строкам из CSV
  • настроить бегущий счётчик чисел без дёрганья ширины шрифта
  • устранить мерцание и рассинхрон кадров при покадровом рендере в Remotion
  • рассчитать плавные переходы рангов и значений между разреженными датами
  • запустить пакетный рендер видеографики для пачки наборов данных

Примеры запросов агенту

  • Сделай bar chart race по данным из файла stats.csv с помощью Remotion
  • Создай анимированный счётчик выручки с форматированием валюты и шрифтом tabular-nums
  • Напиши скрипт пакетного рендера графиков через Remotion CLI для всех JSON в папке data/

Как установить chart-animation

1Через Skills CLI (Vercel)

npx skills add iart-ai/data-animation-skills --skill chart-animation -a claude-code

2Вручную: положить файлы

~/.claude/skills/chart-animation/SKILL.md

Папка скилла целиком; для одного проекта — .claude/skills/chart-animation/

По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов

Вопросы о chart-animation

Как установить chart-animation в Claude Code?

Выполните команду npx skills add iart-ai/data-animation-skills --skill chart-animation -a claude-code. Конфигурация запишется в ~/.claude/skills/chart-animation/SKILL.md.

Что делает chart-animation?

Помогает ассистенту писать надёжный код для генерации видеографики из таблиц. В правила заложены формулы интерполяции кадров, тайминги удержания внимания и привязка графики к кадрам Remotion.

Почему в шаблонах chart-animation запрещены анимации D3 и Chart.js?

При рендере видео кадры просчитываются детерминированно, а встроенные таймеры CSS, D3 .transition() и Chart.js привязаны к реальному времени. Из-за разницы таймеров видео будет мерцать и терять кадры, поэтому любые значения привязывают строго к useCurrentFrame().

Исходный текст

SKILL.md · MIT
---
name: chart-animation
description: This skill should be used when the user asks to "make a bar chart race", "turn a CSV into a video", "build an animated data visualization", "create an animated statistics video", "animate a chart/graph", "make a number counter/ticker", "animate a ranking over time", or "batch-render one chart template across many datasets". Covers data-driven keyframing, value interpolation, rank transitions, counters, pacing, annotation, and template×data batch output.
version: 0.1.0
---

# Data Video

Turn a dataset into a chart that moves with intent: a bar chart race, a growing line, a count-up stat. The craft is mapping numbers to pixels every frame, easing the *value* (not just the opacity), and pacing the data so a viewer can actually read it.

## When to use

- Bar chart race / ranking-over-time (the headline use case).
- Animated line/area reveal, animated counters and number tickers.
- One chart design rendered across many datasets (template × CSV → N videos).

## The one rule that prevents 90% of bugs

**Drive every value from the current frame — never from wall-clock time or a library's internal animation loop.** A video frame is rendered deterministically; if a bar's height comes from a CSS transition or a D3/GSAP/Chart.js animation, it flickers or desyncs because the renderer and the animation clock disagree. Compute the displayed value as a pure function of frame.

```js
import { useCurrentFrame, interpolate } from "remotion";
const frame = useCurrentFrame();
const value = interpolate(frame, [0, 60], [0, 1287], { extrapolateRight: "clamp" });
```

In Remotion, disable all third-party chart animations (`animation: false` in Chart.js, no D3 `.transition()`) and let `useCurrentFrame()` be the only clock. D3 is still great for *scales and shapes* (`scaleLinear`, `scaleBand`, `line()`) — just not its timers.

## Map data → pixels

A chart is two functions: a value scale and a frame interpolator. Keep them separate.

| Layer | Tool | Job |
|---|---|---|
| Value scale | `scaleLinear` / `scaleBand` | data units → px (height, x-position) |
| Frame interpolation | `interpolate` / `spring` | frame → eased progress 0→1 |
| Display value | `round` + `Intl.NumberFormat` | progress → the number a human reads |

```js
import { scaleLinear } from "d3-scale";
const yScale = scaleLinear().domain([0, maxValue]).range([0, chartHeight]);
const barHeight = yScale(interpolate(frame, [0, 45], [0, datum.value], { extrapolateRight: "clamp" }));
```

## Easing value changes

Ease the value the same way you'd ease motion. For a count-up or a bar growing in, `easeOutCubic` reads as "settling on a number." For rank changes, prefer `spring` so a bar that overtakes another has a little weight.

```js
const easeOutCubic = (t) => 1 - Math.pow(1 - t, 3);
const t = easeOutCubic(interpolate(frame, [start, end], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }));
const shown = from + (to - from) * t;
```

Never linearly interpolate a value the viewer is reading unless it's a steady time axis (a clock, a year counter) — linear motion on a headline number feels robotic.

## Counters / number tickers

Interpolate the underlying number, then format on render. Two musts: **round before formatting** (no `1287.4013`), and **fix the digit box** so the layout doesn't jump as digits change.

```js
const n = Math.round(interpolate(frame, [0, 50], [0, 1287], { extrapolateRight: "clamp" }));
const label = new Intl.NumberFormat("en-US").format(n); // "1,287"
// CSS: font-variant-numeric: tabular-nums; line-height: 1;  → no width jitter, no clipping
```

For currency/percent use `Intl.NumberFormat("en-US", { style: "currency", currency: "USD" })`. Tabular figures keep each digit the same width so the number doesn't wiggle.

## Bar chart race — rank transitions

The signature move. Real datasets are sparse (yearly/monthly rows); a smooth race needs **interpolated keyframes between data rows** plus bars that slide to new ranks. The y-position comes from a rank that is itself interpolated, so an overtake animates as a glide, not a jump.

```js
// frame → continuous time between sparse rows, then rank each item by its interpolated value
const t = frame / fps;                  // seconds
const i = Math.min(Math.floor(t), rows.length - 2);
const f = easeInOut(t - i);             // 0→1 within the current row pair
const vals = items.map((it) => ({
  it,
  v: rows[i][it] + (rows[i + 1][it] - rows[i][it]) * f, // interpolated value
}));
vals.sort((a, b) => b.v - a.v);         // rank this frame
vals.forEach((d, rank) => { d.y = rank * (barH + gap); }); // y from interpolated rank
```

Render with stable keys per item (so React tracks each bar across reorders), animate `y` and `width` off the per-frame value, and show a moving year/date label. See `references/bar-chart-race.md` for a complete, runnable Remotion component.

## Pacing data over time

Animation that's too fast is unreadable. Budget time per data event, not per second of polish.

| Beat | Budget | Why |
|---|---|---|
| Intro / first frame | hold 1–1.5s | let the viewer read axes + units before motion |
| Per data row (race) | 0.3–0.6s | fast enough to feel alive, slow enough to track the leader |
| A highlighted moment | +0.5–1s slow-down | dwell on the crossover / record / inflection |
| Final state | hold 2–3s | the takeaway needs to land and be screenshot-able |

Reveal progressively — one series, then the next — instead of all data at once; viewers can only track one moving thing at a time.

## Labeling & annotation

Numbers without context are noise. Always render: an always-visible **value label** on each bar/point (it animates with the value), a **time indicator** (year/date), and **axis units once**. Add a callout only at the moment it matters (a crossover, a peak) — annotate the inflection, then let it fade.

## Template × data — batch output

The payoff of code-driven charts: one design, many datasets. Make the dataset an input prop, never a hardcoded constant, then render once per file.

```jsx
// Remotion: data is a prop; same composition, different CSV → different video
export const Race = ({ data }) => { /* …reads `data`, hardcodes nothing… */ };
```
```bash
# render the same template for every dataset in /data
for f in data/*.json; do
  name=$(basename "$f" .json)
  npx remotion render Race "out/$name.mp4" --props="$f"
done
```

Keep colors/fonts/layout in a single theme object so 50 videos stay brand-consistent and only the numbers change. See `references/data-pipeline.md` for CSV→props parsing, validation, and the full batch script.

## Output checklist

- Every animated value is a pure function of `useCurrentFrame()`; no library timers.
- Numbers are rounded and formatted (`Intl.NumberFormat`), digits use `tabular-nums`.
- Race bars carry stable keys; rank changes glide via interpolated rank.
- Axes/units labeled once; value labels animate with their value.
- Intro hold, readable per-row pace, final hold ≥2s.
- Dataset is an input prop — one template renders every CSV in the folder.

## Deliver & verify (rendered stills → MP4)

> **Packaged helper** (`scripts/`): tile your stills with `scripts/contact-sheet.sh sheet.png f-hook.png f-mid.png f-end.png`, then assert the encode with `scripts/probe-mp4.sh out.mp4 [WxH] [fps]`. See `scripts/README.md`.

Remotion is frame-deterministic — every bar height, counter value, and rank is a pure function of `useCurrentFrame()`, so you can render any exact frame headlessly with no seek harness. The deliverable is an MP4 carrying **exact numbers**, so still-inspection is non-negotiable here: a one-pixel layout bug is forgivable, a wrong digit is not.

**Output contract:**
- A Remotion project with the chart registered (`<Composition>` + zod `schema` + `defaultProps`), all motion frame-driven (no timers / `Date.now()` / `Math.random()`, no Chart.js/D3 `.transition()` clocks).
- Deliverable = the rendered `out/*.mp4` (plus the project, so the user can re-render with new datasets).
- Data-dependent duration (N rows × frames/row)? compute it in `calculateMetadata`, not by hand.

**Verify loop — render stills → inspect → encode.** Render single frames first (cheap, no video encode), then encode only once the numbers and layout are right.

```bash
# 1. Frame-exact stills at start / mid / end (PNG, headless, fast) — with the SHIPPED props
npx remotion still Race out/f-start.png --frame=0   --props='{"data":[...]}'
npx remotion still Race out/f-mid.png   --frame=90  --props='{"data":[...]}'
npx remotion still Race out/f-end.png   --frame=149 --props='{"data":[...]}'  # last = durationInFrames - 1

# 2. Inspect each PNG — FIDELITY (axis labels, value labels, year/date, ranks, units all EXACT —
#    round + tabular-nums working, no 1287.4013) AND artifacts (bar overflow, off-canvas label,
#    clipped safe-area, missing font, wrong data binding / wrong column mapped).

# 3. Only after the stills check out, encode:
npx remotion render Race out/race.mp4 --props='{"data":[...]}'
```

- Use `npx remotion compositions` to read each chart's `durationInFrames`/`fps` and pick the end frame.
- **Data-driven / batch (the headline case)**: verify ONE representative dataset via stills *before* batch-rendering all N files — a height-scale or column-mapping bug caught once beats finding it in 50 MP4s.
- **README demo GIF for free**: `npx remotion render Race out/demo.gif --codec=gif`.

**Before you finish:**
1. `npx remotion still` renders cleanly at frame 0, mid, and last — no errors, no missing fonts/assets.
2. Every number is **exact** (rounded, `Intl.NumberFormat`, `tabular-nums`) and inside the safe area at each frame.
3. Frame-driven only — no `Date.now()` / `Math.random()` / library timers (determinism holds in CI).
4. The **shipped** dataset props render correctly (not just `defaultProps`) — right column mapped, right scale.
5. Full MP4 encoded and plays; (optional) GIF rendered for the README.

## Reference files

- `references/bar-chart-race.md` — a complete runnable Remotion bar-chart-race component: sparse-row keyframe interpolation, per-frame ranking, gliding y-positions, animated value labels, and a D3-scale axis. Plus a vanilla canvas variant.
- `references/data-pipeline.md` — CSV/JSON → typed props parsing and validation, the theme object pattern, animated counters/line-reveal recipes, and the template×data batch render script for N videos.

© iart-ai · MIT · iart-ai/data-animation-skills

Похожие скиллы

Все скиллы по теме «Данные и базы» →
xlsx официальный anthropics Работает с табличными файлами: создаёт, читает, правит и преобразует книги. Подходит, когда итогом должен стать файл Excel или другой табличный формат. 187 223установок google-agents-cli-observability официальный Google Помогает настроить трассировку и сбор данных о работе ИИ-агентов, включая агентов на ADK. Пригодится, когда нужно разбирать выполнение запросов или наблюдать за агентом после развёртывания. CX Codex +1 511 300установок caveman-evidence-review JuliusBrussee Скилл читает данные Caveman Cloud о расходах LLM, трассах и маршрутизации. Подходит для проверки того, куда уходит бюджет проекта. CX Codex +1 104 500установок migration JuliusBrussee Скилл задаёт правила безопасных миграций схем, данных и API с обязательным откатом. Пригодится при изменениях, где нельзя терять данные или ломать совместимость. CX Codex +1 103 900установок performance-optimization addyosmani Скилл для агентов ИИ-кодинга: сначала замеряет, потом чинит узкое место — от Core Web Vitals до N+1 запросов и индексов в базе. CX Codex +1 65 200установок supabase официальный supabase Скилл помогает настраивать базу данных, аутентификацию и RLS в Supabase без скрытых дыр в безопасности. CX Codex GP ChatGPT 8установок

Из того же набора3

Спонсоры проекта

Компании, которые помогают держать аналитику открытой