mcpField
D
data-story-charts

data-story-charts

github.com/phantomtonytクリエイティブ・メディア24164 回インストール4 週間前に更新
リポジトリ

data-story-charts について

Data Story Chartsは、データを短い解説動画にするためのチャートアニメーションスキルです。データを紹介する制作者向けに、数値、チャート、注釈をストーリー順に表示し、出典と正確性を重視します。

主な機能

  1. 01折れ線、棒、積み上げ、カウンターチャート
  2. 02チャートと同期する数値カウンター
  3. 03ストーリー順のデータ表示
  4. 04重要なデータ点への注釈
  5. 05滑らかな軸スケール変更

活用シーン

  1. 01データの変化を短い動画にする
  2. 02傾向のピークや転換点を強調する
  3. 03注釈で重要な数値を説明する

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/phantomtonyt/motion-design-skills --skill data-story-charts

インストール後、Claude Code で/data-story-chartsを入力して読み込まれたか確認します。

詳細

データストーリーチャート

ストーリーの順に組み立て、順番に明かしていく1つのチャートです。主役は数字です。上部に大きなカウンターを配置し、それに合わせて動く折れ線や棒、変化の理由を伝える注釈ピンを添えます。解説報道のような、明快で落ち着いた印象を目指し、ドラマチックな場面は1〜2回にとどめます。

オプション

オプションデフォルトメモ
形式縦型 1080×1920または横型 1920×1080
長さ15–20 sデータの展開1つにつき約3–5 s
チャート折れ線line(時間による変化)、bars(比較)、stacked(合計の内訳)、counter(大きな数字を1つ)
トーンエディトリアルeditorial(デフォルト、明るい紙面)、dark(ネイビー、光るアクセント)、punchy(テンポが速く、重要な場面で色が切り替わる)

ブリーフ(計画の前に回答)

  1. 視聴者に覚えてほしい数字または変化は何ですか?
  2. データは何ですか(貼り付けるか、ファイルを指定してください)。単位、期間、出典も記載してください。
  3. 意外な点は何ですか。急増、急落、逆転、隠れたコストなどですか?
  4. 注釈ピンを付けるべき場面はどの2〜4か所ですか?
  5. 締めくくりの一文は何ですか?

ユーザーが提示した実際の数値か、データから計算した数値だけを使用してください。データを捏造してはいけません。推定値の場合は、画面上でその旨を明記してください。

読み取りシート(ビートリストと一緒に作成)

各ビートについて、視聴者が理解しなければならないことを1つ(「ロボットは飛べない」「キャッシュがヒットしなかった」など)と、それを読み取れる状態で表示する時間を記載してください。一度に読み取る内容は1つだけにします。テキスト表示時間の下限:ラベルは最低0.8 s、文は画面に完全に表示されてから単語あたり約0.3 s。表示時間に収まらない場合は、速度を上げずに言葉を削ってください。

モーションの原則

  • モーションには因果関係を持たせます。画面上の理由(クリック、落下、パケットの到着など)に応じて動かし、次の動きはその結果としてつなげます。
  • 動画全体を通して、主な移動方向を1つ選び、それを維持します。それ以外の方向は意味を持たせて使います。成功や結論には上方向、「全体像はこちら」にはズームアウトを使います。
  • シーンの退出を次のシーンの登場につなげます。同じ軸、同じ方向、似た速度を使います。クロスフェードではなく、変化をまたいで1つのオブジェクトを引き継ぎます。
  • 図、チャート、テキストに目的のない埋め草の動き(浮遊、呼吸、揺れ)を加えません。動かす必要がなければ静止させます。意図的なカメラの動きは1つで十分です。
  • イージング:登場時は滑らかなイーズアウト(power2.out から power4.out)、退出時はより素早いイーズイン(登場時間の約75%)。登場は最大0.8 s。グループ全体のスタッガーは最大0.5 s。オーバーシュート(back.out)は小さなポップに限り、弾性やバウンスは使いません。
  • 重要な場面では、一度に動かすものは1つにします。視線が追えるのは1つだけです。
  • 見せ場の直前に、0.3〜0.75 sの静止時間を設けます。

スタイルルール(常に適用)

  1. シーンごとのチャートタイプは1つ、焦点を当てる系列も1つにします。それ以外の系列はグレーにします。
  2. チャートは時間の経過またはストーリーに沿って表示します。線は左から右へ描き、棒は順番に伸ばします。話題にする前に表示してはいけません。
  3. 大きなカウンターには現在の値を表示し、チャートに合わせて数値を更新します(等幅数字)。
  4. データが軸の範囲を超えたら、画面上で軸を再スケーリングします(目盛りとラベルをイーズ付きで変化させます)。この再スケーリングは、通常、動画の最も見せ場になる瞬間です。
  5. ピンを使って、重要な2〜4か所に短いラベルを付けます。
  6. すべてのラベルでコントラスト比3:1を確保します。グリッドと目盛りラベルには、薄いグレーではなく落ち着いたダークグレーを使います。

デフォルトと上書き

優先順位:ユーザーのブランドまたは仕様、明示的なリクエスト、これらのデフォルトの順です。

  • エディトリアル:紙 #f7f4ee、インク #16213a、グリッド #e3ded4、目盛りラベル #5b6270、アクセント #e4572e、プラス #047857、警告 #a16207、マイナス #c2410c。
  • ダーク:ステージ #0f1724、インク #f2f5f9、グリッド #1f2b3d、ラベル #9fb0c8、アクセント #38d6e0。
  • フォント:Inter(カウンターは900、140–170 px、キャプションは800、56–64 px、ラベルは600、26–30 px)。

セットアップ(1回)

node -v && ffmpeg -version
npx hyperframes init my-video --non-interactive --resolution portrait && cd my-video   # landscape for 16:9

種類

必要なものHyperFrames の SVG + GSAP(デフォルト)RemotionHyperFrames 内の D3
線、棒、カウンター、ピンはいはいはい
数千個の点または地図投影負荷が高い負荷が高いはい(時刻 t から描画)
Node と FFmpeg だけで動作はいはいはい

レイアウト

  • 9:16: キッカーラベルを y 285、カウンターを y 350(150 px)、グラフ領域を x 120–960、y 520–1000 に配置し、軸ラベルをその下に、キャプションを y 1110–1250 に配置します。
  • 16:9: カウンターを左上、グラフを x 200–1720、y 260–880 に配置し、キャプションを左下またはグラフの右側に配置します。
  • ピンは破線の軸線を付けてデータポイントの上に配置します。カウンターやキャプションに重ならないようにします。

アニメーション方法(シークセーフ)

データを関数または配列として記述し、1 つのクロック値 t からグラフ全体を描画します。1 つのトゥイーンでクロックを動かし、その onUpdate で再描画します。

const clock = { t: 0 };
tl.to(clock, { t: DURATION, duration: DURATION, ease: "none", onUpdate: () => draw(clock.t) }, 0);
draw(0);

draw(t) は t までの折れ線パスを再構築し、マーカーとカウンターを動かします。また、現在の軸の最大値(それ自体も t の関数です)に基づいてピンと軸ラベルを配置します。すべてのピクセルが t から決まるため、HyperFrames がシークしても、どのフレームも常に同じようにレンダリングされます。

動き方法
線の表示t までのサンプルからパスを構築します(データ 1 秒あたり約 30 個)。
線の下の塗りつぶし同じパスをベースラインまで閉じ、アクセントカラーを不透明度 12% で適用します。
棒の伸長高さを 0 からトゥイーンし、0.08 s ずつずらして開始します。power3.out を使用します。
カウンター現在の値をテキストで表示します。10 未満は小数第 1 位まで、それ以上は整数で表示します。
軸の再スケーリングyMax(t) を 1~1.5 s かけて古い最大値から新しい最大値へ滑らかに変化させ、目盛りラベルも更新します。
ピンのポップピンの時刻に back.out(2.5) を使って、スケールを 0.5 から 1 にします。
強調重要な数値の表示中、カウンターを 1.12 倍に拡大してから元に戻します。

目を引く仕上がりにする

  • 最初のフレームから、カウンター、軸、問いが表示されています。
  • 驚きを与える場面では、0.5 秒以内に再スケーリング、ピンの表示、キャプションの変更をすべて行います。
  • 小さなマーカー(点、アイコン、キャラクター)を線の先端に沿って動かし、視線を誘導します。
  • 面の塗りつぶしと先頭の点に加える柔らかなアクセントの光で、画面を散らかさずに奥行きを出します。
  • キャプションは短い文にし、数値をアクセントカラーで表示します(「その後:120 m.」)。
  • 静止したどのフレームにも、それ単独で事実が示されています。

スターター

<div id="root" data-composition-id="main" data-start="0" data-duration="10" data-width="1080" data-height="1920" style="background:#f7f4ee;font-family:Inter,sans-serif">
<svg viewBox="0 0 1080 1920" width="1080" height="1920" style="position:absolute;inset:0">
  <g id="grid" font-size="26" fill="#5b6270"></g>
  <line x1="120" y1="1000" x2="960" y2="1000" stroke="#16213a" stroke-width="4"/>
  <path id="area" fill="#e4572e" opacity=".12"/><path id="line" fill="none" stroke="#e4572e" stroke-width="9" stroke-linejoin="round" stroke-linecap="round"/>
  <circle id="dot" r="14" fill="#e4572e"/>
</svg>
<div style="position:absolute;left:60px;top:350px;font:900 150px/1 Inter,sans-serif;color:#16213a;font-variant-numeric:tabular-nums"><span id="num">0</span></div>
</div>
<script>
const D = 10, X0 = 120, X1 = 960, Y0 = 1000, Y1 = 520;
const data = (t) => 2 * t + (t > 6 ? 40 * ((t - 6) / 4) ** 2 : 0);          // replace with the user's data
const yMax = (t) => 20 + 60 * Math.min(1, Math.max(0, (t - 6.5) / 1.2));    // axis rescales at the surprise
const px = (t) => X0 + (X1 - X0) * (t / D), py = (v, m) => Y0 - (Y0 - Y1) * (v / m);
const NS = "http://www.w3.org/2000/svg", grid = document.getElementById("grid");
const ticks = [0, 0.5, 1].map((f) => { const l = document.createElementNS(NS, "line"), x = document.createElementNS(NS, "text");
  l.setAttribute("x1", X0); l.setAttribute("x2", X1); l.setAttribute("stroke", "#e3ded4"); x.setAttribute("x", X1); x.setAttribute("text-anchor", "end"); grid.append(l, x); return { f, l, x }; });
function draw(t) {
  const m = yMax(t); let d = "";
  ticks.forEach(({ f, l, x }) => { const y = Y0 - (Y0 - Y1) * f; l.setAttribute("y1", y); l.setAttribute("y2", y); x.setAttribute("y", y - 10); x.textContent = Math.round(m * f); });
  const n = Math.max(2, Math.round(t * 30));
  for (let i = 0; i <= n; i++) { const s = (t * i) / n; d += (i ? "L" : "M") + px(s).toFixed(1) + " " + py(data(s), m).toFixed(1); }
  document.getElementById("line").setAttribute("d", d);
  document.getElementById("area").setAttribute("d", d + "L" + px(t) + " " + Y0 + "L" + X0 + " " + Y0 + "Z");
  const dot = document.getElementById("dot"); dot.setAttribute("cx", px(t)); dot.setAttribute("cy", py(data(t), m));
  document.getElementById("num").textContent = Math.round(data(t));
}
const tl = gsap.timeline({ paused: true }), clock = { t: 0 };
tl.to(clock, { t: D, duration: D, ease: "none", onUpdate: () => draw(clock.t) }, 0);
draw(0);
window.__timelines["main"] = tl;
</script>

GSAP(https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js)、Google Fonts の Inter フォント、および html,body{margin:0;width:1080px;height:1920px;overflow:hidden} を含む <head> を追加します。同じタイムラインにキッカー、キャプション、ピンを追加します。

公開するパラメーター

format · duration · chart · tone · data(配列または関数) · units · pins(時刻、ラベル、色) · captions(時刻、テキスト) · rescaleAt。

避けること

  • 画面上の数値はすべて、ユーザーのデータまたは出典を引用したものにします。コンポジションの横に、小さな事実リスト(数値、出典)を置きます。説明用の数値は、画面上で説明用と明記します。
  • 作り出した数値や「説明用」の数値を、実際の数値として表示すること。
  • 複数の系列を同時に強調することや、虹色のパレット。
  • 薄いグレーのラベル(コントラストチェックに通らず、スマートフォンでは読めません)。
  • グラフを見づらくする要素:3D の棒、濃いグリッド線、直接ラベルで済む場合の凡例。
  • 軸をイージングなしで急に動かすこと。変化が視聴者に伝わるよう、滑らかに再スケーリングします。
  • ピンやキャプションで、線の重要なポイントを覆うこと。

失敗しやすいポイント

状況原因対処法
レンダリング時に線が飛んだりちらついたりする壁時計の時刻やフレームごとの乱数を使って描画しているonUpdate ではクロック t のみを使って描画します
ピンのラベルがピルからはみ出すピルの幅を小さく見積もっている28 px では幅を約 36 + 文字数 × 17(すべて大文字の場合は × 23)にするか、フォントの読み込み後に測定します
キッカーとカウンターが重なるどちらも近すぎる位置に配置されているキッカーのベースラインとカウンターの上端の間を 30 px 以上空けます
驚きの演出が平坦に見えるスケール変更、ピン表示、キャプション変更がない3つすべてを 0.5 秒以内に重ねて実行します
カウンターの文字が揺れるプロポーショナル数字を使っているfont-variant-numeric: tabular-nums
目盛りのコントラストチェックに失敗するラベルの色が明るすぎる明るい背景では目盛りを #5b6270、暗い背景では #9fb0c8 にします

検証

npx hyperframes check
npx hyperframes snapshot --at <start, each pin, mid-rescale, end>
npx hyperframes render -o renders/<name>.mp4
  • 画面上の数値が、それぞれの時点のデータと一致している
  • スケール変更が滑らかで、その間もラベルが読みやすい
  • ピンやキャプションが、線の重要なポイントに決して重ならない
  • すべてのテキストがセーフエリア内にあり、コントラストチェックに合格している
  • 最終フレームで要点を伝えている

最終レンダリング前の自己評価

スナップショットシートを、引き(最初の1秒)、スマートフォン幅での読みやすさ、動きの質、構図、正確さ、「ミュートテスト」(音なしで視聴者が一文で要約できるか)の各項目について、1〜10点で評価します。7点以下の項目だけ修正し、再度スナップショットを作成して、すべてが8点以上になるまで繰り返します。可能であれば、自分の作品を評価するのではなく、別の読み取り専用の工程で採点してもらいます。

避けること代わりにすること
情報量の多い2つのレイアウトをクロスフェードする古いコンテンツを退出させてから新しいコンテンツを表示するか、1つのオブジェクトを引き継ぎます
複数の要素を同時に動かすタイミングをずらし、その瞬間に注目させる要素を1つにします
間を埋めるために浮遊や揺れを加える静止させるか、キャラクターに動作させます
「勢い」を出すためにパーティクル、レインボーグラデーション、3D フリップを加えるより強いイベント、たとえば表示、衝突、カメラ移動を加えます
時間内に収めるためにテキストを急いで表示する言葉を削ります

納品

  • ポスター:最終チャートの静止フレームをフレーム 0 に埋め込みます:ffmpeg -ss <t> -i renders/<name>.mp4 -frames:v 1 poster.jpg、次に ffmpeg -i renders/<name>.mp4 -i poster.jpg -filter_complex "[0:v][1:v]overlay=enable='eq(n,0)'" -c:a copy renders/<name>-final.mp4 を実行します。
  • 重要な数値とデータソースを記載したキャプション。
  • データの展開と、修正時に変更する数値やピンをユーザーに伝えます。

参考資料

  • @kimmonismus、「A Short History of AI」。Remotion で制作された、マイルストーンカウンター付きのタイムライン:https://x.com/kimmonismus/status/2102844654169575547
  • @VincentWei93、Anthropic の成長をデータビジュアライゼーションのモーショングラフィックスで表現した作品。数値に合わせた効果音付き:https://x.com/VincentWei93/status/2103381720410333314
  • @sonnylazuardi、インドネシアの81年間の歴史を42,000点のドットマップで表現した作品:https://x.com/sonnylazuardi/status/2103511590884815282
  • @aakashgupta、積み上げ棒グラフとカウンターで報酬オファーの内訳を示した作品:https://x.com/aakashgupta/status/2102998741359988832
  • HyperFrames のモーションドクトリンと、顔出しなしの解説動画のスキル、JohnHeibel/ClaudeAnimationBase のアニメーションガイド、howseen-ai/claude-motion-design の批評ループ、latent-spaces/brag から着想を得ています(コピーではありません)。

コメント