lottie-animator について
lottie-animatorは、Lottieアニメーションの作成と検証を支援するスキルです。再利用可能なPythonレシピ、Lint、レンダリング、パレット、SVG変換を組み合わせ、JSONの妥当性だけでなく画面上の見た目も確認します。
主な機能
- 0122種類のアニメーション生成例
- 02LottieのLintとフレーム確認
- 03役割別の9色パレット
- 04SVGからLottie図形への変換
- 05タイミングとイージングの指針
活用シーン
- 01既存レシピを使ったローダー作成
- 02空白やはみ出しのあるフレームの確認
- 03既存Lottieファイルの配色変更
- 04SVGアイコンのLottie図形への変換
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ obeskay/ lottie-animator-skill --skill lottie-animatorインストール後、Claude Code で/lottie-animatorを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/disney-principles.mdexamples.mdlottie-gsap-integration.mdlottie-structure.mdlottie-tools-ecosystem.mdmotion-taste.mdprofessional-techniques.mdshape-modifiers.mdsvg-to-lottie.md詳細
Lottie Animator
Lottie は JSON なので、簡単に書ける一方で、誤って書くのも簡単です。特有の厄介な問題があります。壊れた Lottie でも解析は通ります。 polystar の os が欠けている、イージングハンドルの階層が一段深すぎる、ip/op のないレイヤーがある――ファイルは読み込まれ、プレイヤーはエラーを報告せず、キャンバスは空のままです。正しいファイルでも、見栄えが悪いことはあります。直線的、弾みすぎ、詰め込みすぎ、紫色。
そのため、JSON が有効かどうかでアニメーションを判断しないでください。実際に見て判断してください。
以下のパスは、このスキルのディレクトリからの相対パスです。別のプロジェクトから使う場合は、絶対パスで指定してください。レンダラーを使うには、package.json があるリポジトリで一度 npm install を実行する必要があります。
最短ルート:レシピから始める
examples/ には、完成済みでリンティングとレンダリングを済ませたアニメーションを生成する Python ファイルが 22 個あります。白紙から始めるより、最も近いものをベースにするほうが効率的です。タイミング、イージング、構造はすでに適切なので、変更するのはジオメトリと動きの要点だけです。
| 要望 | ベースにするもの | 学べること |
|---|---|---|
| 成功、完了、保存 | success-check | 静止する円盤上でのトリム描画と、控えめな波紋 1 つ |
| エラー、無効、拒否 | error-shake | 主役となる、次第に弱まる揺れ |
| いいね、お気に入り、リアクション | heart-like | 押す → ポップ → 破裂。遊び心のあるトーンと、その明示 |
| 通知、アラート | notification-bell | 上部の支点を中心とした揺れと、クラッパーの余韻 |
| トグル、スイッチ、設定 | toggle-switch | 暗い背景での移動と色のトラック |
| ロック、プライバシー、アクセス | lock-unlock | 脚を軸に開くシャックルと、状態に応じた色 |
| 再生、一時停止、アイコン間の変化 | play-pause、shape-morph | 頂点数を合わせたパスのモーフィング |
| 読み込み、待機 | spinner-arc、typing-dots、panda-loader | トリムの追いかけ、時間差のある波、キャラクターのループ |
| 進行状況、ダウンロード、充電 | download-progress、battery-charge | 重なり合うフェーズ、段階的な塗りつぶし |
| オーディオ、ライブ、録音 | equalizer | 基部に固定した、位相をずらしたバー |
| 位置情報、プレゼンス | location-ping | 遠近感のある、時間差で広がるリング |
| 天気、アンビエント | weather-sun | レイピートの光線を、間隔ちょうど 1 つ分だけ回転 |
| 送信、共有、移動 | paper-plane | 空間タンジェント:弧に沿った動きとバンク |
| お祝い、報酬 | confetti-burst | 弾道を描く弧と、最大 3 色 |
| カード、オンボーディング、リスト | card-stack | 滑らかに連なるカスケード。主役が最後に着地 |
| ロゴの表示 | logo-draw-on、rocket-launch | SVG → Lottie、読み順に沿ったストロークの描画 |
| バウンス、物理挙動 | bouncing-ball | 体積を保ったスクワッシュとストレッチ |
cp examples/spinner-arc.py build/loader.py
# edit build/loader.py: point its sys.path line at this skill's scripts/ directory,
# then change the geometry and beats to the brief — keep the tokens
python3 build/loader.py --palette night -o build/loader.json
各ジェネレーターの docstring には、その概要(雰囲気、トーン、主役となるプロパティ)が記載されています。変更しても、うまく機能していたアイデアが失われないよう、編集前に読んでください。同じファイルをどの配色でもレンダリングできます。そのため、「ダークモードに合わせる」には書き直すのではなく、--palette night を指定します。
作業の流れ
build → lint → render → LOOK → revise
レンダリングを省略しないでください。「JSON は有効です」は、ユーザーにどう見えるかについての主張ではありません。
python3 scripts/lottie_lint.py build/loader.json --strict
node scripts/render.mjs build/loader.json
# Read the filmstrip PNG it prints and actually look at it
node scripts/render.mjs build/loader.json --onion
# the taste pass: Read onion.png and judge the motion, not just the pixels
render.mjs は filmstrip.png を出力します。ファイルが想定する背景(meta.tc。--bg で上書き可能)に、タイムライン全体のフレームをラベル付きで並べ、各フレームのシェイプ数とキャンバスの占有率も表示します。何も描画されない場合(レイヤーの不透明度が 0 になった場合も「何もない」とみなされます)は EMPTY FRAME、アートがフレームの外に出た場合は off canvas、端を越えた場合は clipped と報告します。これでアニメーションが壊れていないことを確認できます。見栄えがよいかどうかは、さらに確認が必要です。--onion は onion.png を出力します。サンプリングしたフレームを古い順に薄く重ねた画像で、残像の間隔がイージングを、その軌跡が弧を表します。references/motion-taste.md の品質確認項目に照らして判断してください。
ツールを利用できない場合(別のリポジトリを使っている、Node がないなど)は、その旨を伝え、代わりに python3 -c "import json; json.load(open('a.json'))" を実行してください。ただし、確認済みであるかのように伝えるのではなく、結果は未検証であることをユーザーに伝えてください。
ジェネレーターの作成
scripts/motion.py はハウススタイルをコードに変換するため、ジェネレーターでハンドル、16 進数の値、必須プロパティを手入力する必要はありません。
import sys; sys.path.insert(0, "<skill>/scripts")
from motion import *
def build(c): # c is a palette, by role
disc = layer("Disc", group("Disc", ellipse(128), fill(c["accent"])),
p=(120, 120),
s=track((0, [92, 92], "out"), (22, [100, 100])),
o=track((0, 0, "out"), (10, 100)))
return comp("Disc", 240, 240, [disc], op=90, bg=c["bg"])
if __name__ == "__main__":
main(build, __file__, palette="paper") # --palette NAME, -o PATH
track((t, value, ease), ...)は最後を除くすべてのキーフレームにハンドルを設定するため、キャンバスがフリーズする不具合は発生しません。delay(track, n)でオフセットしてカスケードを作れます。4 つ目の要素({"to": ..., "ti": ...})を追加すると、位置が弧を描いて移動します。- 形状:
ellipse、rect、star、path(squircle(w, h, r))、および任意の SVG パスデータを指定できるsvg(d, scale, center)。描きやすいグリッド上に描き、centerでピボットを図形の中央に移動します。描画:fill、stroke(dash=...)。モディファイア:trim、repeater、round_corners。構造:group(ジオメトリ、描画、次にそのトランスフォーム)、layer(マットにはparent="Name"、td/tt)、null、comp。 shapesリストとレイヤーリストでは、先頭の項目が最前面に描画されます。
パレット
9 つのパレットで 7 つの役割(bg(背景色。meta.tc に格納)、surface、ink、muted、accent、on_accent、support)を共有し、テストでそれぞれのコントラスト比を確認します。パレットは paper、night、dusk、harbor、citrus、berry、forest、mono、sky です。役割に沿って記述すれば、どのパレットでも使えます。1 つのコンポジションにつきアクセントは 1 色にし、support は面に使用します。背景上の細い線には使わないでください。
- ブランドカラー: 同じ 7 つの役割を持つ dict を
PALETTESに追加し、コントラスト比を確認します。 - 既存ファイル: LottieFiles、デザイナーなど、入手元を問わず、
python3 scripts/recolor.py in.json --listを実行すると、各色の用途とレイヤーがすべて表示されます。次に、各役割について--map "#FF5A5F=#C8522B" -o out.jsonを実行します。静的およびアニメーションの描画、グラデーションの停止点、ソリッドレイヤーに対応しています。 - ダークモード: ホストで使われるすべての背景色でレンダリングします。背景と同じ明度の色で描いた線は、コントラストが低いのではなく見えません。レンダリングして初めて確認できます。
実際のジオメトリから始める
ベジェ頂点を手書きしないでください。svg2lottie.py は SVG のパス、矩形、円、楕円、線、多角形、ポリライン、グループ、トランスフォーム、ストローク、線形/放射状グラデーションを Lottie のシェイプレイヤーに変換します。各要素はそれぞれ独立した名前付きレイヤーとなり、要素自体の中心を基準に配置されるため、拡大縮小や回転のピボットが正しく設定されます。
python3 scripts/svg2lottie.py icon.svg -o icon.json --size 512 --current-color "#1E1B18"
アイコンセットは currentColor で描画されます。--current-color を指定しないと、アートワークは黒で出力されます。<text>、<use>、clipPath、mask は警告として報告されます。あらかじめソース SVG でこれらをフラット化してください。出力は意図的に静的なものです。convert() を使って Python から(examples/rocket-launch.py を参照)、または手作業でモーションを追加します。
キーフレームを設定する前に、動きを決めます
キーフレームに触れる前に、次の点に答えてください。30 秒で済み、ほとんどの修正サイクルを防げます。
- 感情 — 見る人にどんな気持ちになってほしいですか?(信頼、喜び、緊急性、落ち着き)
- 表現のトーン — 指示がない限り、静かで正確にします。オーバーシュートはゼロ、点から大きくなる動きはなし。弾みのある遊び心のある動きは、求められた場合に限ります。
- 主役となるプロパティ — 位置、スケール、回転、不透明度、形状のいずれか一つです。ほかのプロパティは、それを補うために振幅を 3 分の 1 未満に抑えます。
- タイミング — フィードバックは 60 fps で 6~10 フレーム、登場は 18~30 フレーム、ずらしは 3 フレーム、ループの繰り返し前には少なくとも 12 フレーム保持します。
- イージング — 登場には
out、移動とループにはin-out、退場に限りinを使います。 - 配色 — 役割ごとに色を割り当て、アクセントカラーは一色にします。紫のグラデーションや黒地にネオンは使いません。
被写体と競い合う動きはノイズです。削除してください。原則の全容、トークン、センスのチェックについては、references/motion-taste.md を参照してください。
トピック別の詳しい手法: shape-modifiers.md(トリム、リピーター、オフセット、マージ)・ professional-techniques.md(親子付け、リグ、歩行サイクル、プリコンポーズ)・ disney-principles.md・ lottie-gsap-integration.md(スクロールに連動したスクラブ)・ lottie-structure.md・ svg-to-lottie.md・ examples.md・ lottie-tools-ecosystem.md(dotLottie、プレーヤー)
イージング
ハンドルはキーフレームの中に置きます。保持するプロパティの中には置きません。x は 0~1 の範囲内にする必要があります。y は範囲を超えてもよく、それによってオーバーシュートを作れます。そのため、標準設定では y を 0~1 の範囲内に保ちます。
キーフレーム n のハンドルは、n から n+1 までの区間の形状を決めます。誤ったキーフレームにハンドルを置くと、動きの誤った半分にイージングが適用されます。
最後のキーフレームを除くすべてのキーフレームには、動きがリニアな場合も両方のハンドルを設定します。ハンドルのないキーフレームは、lottie-web では「リニア」ではありません。補間中にプレーヤーがエラーを投げ、レンダリング処理が中断され、コンソールには何も表示されないまま、キャンバスが直前のフレームで停止します。ホールドキーフレーム(h: 1)だけが例外です。
トークン(motion.py) | 用途 | cubic-bezier |
|---|---|---|
out | 登場、フィードバック | 0.23, 1, 0.32, 1 |
in-out | 移動とモーフィング、静止状態から静止状態への動き | 0.77, 0, 0.175, 1 |
glide | 大きな面 | 0.32, 0.72, 0, 1 |
in | 退場のみ | 0.55, 0, 1, 0.45 |
linear | 一定の回転、一定間隔で移動するオフセット | 0.333, 0.333, 0.667, 0.667 |
swing | 振り子、振動、呼吸 | 0.37, 0, 0.63, 1 |
standard | スピナーの追従、レベルメーター | 0.4, 0, 0.2, 1 |
strike | 打撃後の最初の振り | 0.61, 1, 0.88, 1 |
fall / rise | 重力、正確な t² の動きとその反転 | 0.333, 0, 0.667, 0.333 / 0.333, 0.667, 0.667, 1 |
playful | オーバーシュート。求められた場合のみ | 0.34, 1.56, 0.64, 1 |
ハンドルとして、cubic-bezier(x1, y1, x2, y2) は、動きが始まるキーフレーム上で "o": {"x": [x1], "y": [y1]} および "i": {"x": [x2], "y": [y2]} となります。静止しない動きには linear、swing、standard が適しています。振動に in-out を使うと、折り返すたびに停止し、その間で急に動きます。
空白表示になる不具合
以下の不具合はすべて、かつてこのリポジトリに含まれており、JSON の解析チェックにも合格していました。現在はリンターがすべて検出し、テストで再発を防いでいます。
| 症状 | 原因 |
|---|---|
| ファイル全体が空白で、コンソールエラーもない | イージングハンドルがキーフレーム内ではなくプロパティにある(KF011) |
| レイヤーが1つ表示されない | レイヤーに ip、op、st がなく、再生ヘッドがそのレイヤーに一致しない(LY005) |
| レイヤーが1つ表示されない | シェイプ項目に必須プロパティがなく、プレーヤーがレイヤーを破棄する(SH001) |
| ジオメトリはあるが、何も見えない | グループに塗りまたは線がない(LY015)、あるいは不透明度が全体を通して 0(LY016) |
| アートの一部がまったく表示されない | 上に列挙された不透明な兄弟レイヤーの下にグループが描画されている(SH004) |
| シェイプがサイズ 0 で描画される | ジオメトリが gr グループ内ではなく、shapes 内にそのまま置かれている |
| アートの位置がずれている | レイヤーのトランスフォームとグループのトランスフォームの両方に同じオフセットが適用されている |
| 周回ごとに目に見えるジャンプがある | 最初と最後のキーフレームの値が異なる(KF010) |
| エラーなしでキャンバスが1フレームに固定される | 最後以外のキーフレームに o/i ハンドルがないため、lottie-web がレンダリング中に例外をスローし、処理が中断する(KF012) |
| 動きが機械的に感じられる | 始動・停止する動きにリニアハンドルが使われている(KF007、注記。一定速度の回転や行進するオフセットは対象外) |
すべてのレイヤーに ip、op、st が必要です。1つでも欠けると、そのレイヤーはすべてのフレームで非表示になります。
プロパティがないとプレーヤーがレイヤーを破棄する項目 — 動作するファイルから該当プロパティを削除し、結果をレンダリングしてそれぞれ検証済みです。
塗り c,o · 線 c,o,w · グラデーション塗り s,e,g,o · ポリスター p,r,pt,or,os、さらに sy が 1 の場合は ir,is · 楕円 p,s · 長方形 p,s,r · トリム s,e,o · トランスフォーム o。さらに sk がある場合は sa も必要です。
仕様では、トランスフォームの a,p,s,r とグラデーションの t も指定されています。lottie-web はこれらにデフォルト値を補うため、リンターはエラーではなく警告(SH003)として報告します。ただし、ほかのプレーヤーも同じように寛容とは限りません。
仕上げ
完了と伝える前に、以下を確認してください。
lottie_lint.pyでエラーが報告されないこと(警告も失敗扱いにするには--strictを使用します)。2つの見た目に関する注記 — 点から何かが成長するKF013、イージングがオーバーシュートするKF014— は、生成された動きによく見られる兆候です。依頼内容で遊び心のある動きが求められていない限り、修正してください。render.mjsで、意図した動きが開始・中間・終了時に確認できること。- ループの場合、最初と最後のフレームが一致すること。数値ではなく、フィルムストリップで確認してください。
- motion-taste.md に記載された見た目の確認を
onion.pngに対して実施済みであること。間隔にイージングがかかっている、移動軌跡が長く滑らかである、点から何も成長しない、主役が1つ、読み取れる停止時間がある、アクセントカラーが1色であること。 - 意図的な場合を除き、クリッピングやキャンバス外へのはみ出しがないこと。
- ホストにダークモードがある場合は、背景ごとに1回レンダリングしてください(ジェネレーターには
--palette、完成済みファイルには--bgを使用します)。
確認したことと、確認していないことを報告してください。レンダリングできなかった場合は、動きを確認したかのように述べず、その旨を明確に伝えてください。