mcpField
L
lottie-animations

lottie-animations

github.com/freshtechbroデザイン・UI1.2k3.0k 回インストール49 週間前に更新
リポジトリ

lottie-animations について

ウェブ、iOS、Android、React NativeアプリにLottieアニメーションを組み込むためのスキルです。After Effectsから書き出したアニメーションの描画、再生制御、操作連携、性能最適化を解説します。

主な機能

  1. 01JSONとdotLottieアニメーションの描画
  2. 02再生・一時停止・シーク・ループ制御
  3. 03スクロールやホバーとの連動
  4. 04React、Vue、Svelteへの統合
  5. 05アニメーションの圧縮と性能調整

活用シーン

  1. 01ボタンやアイコンへのアニメーション追加
  2. 02ローディングや進捗表示の作成
  3. 03オンボーディングアニメーションの構築
  4. 04ページスクロールに合わせた再生

インストール

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

$npx skills add https://github.com/freshtechbro/claudedesignskills --skill lottie-animations

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

assets/starter_lottie/
README.md
references/
after_effects_export.md
api_reference.md
performance_guide.md
scripts/
generate_lottie_component.py
optimize_lottie.py

詳細

Lottie アニメーション

概要

Lottie は、Web、iOS、Android、React Native 上で After Effects のアニメーションをリアルタイムにレンダリングするライブラリです。Airbnb によって開発され、デザイナーは静的アセットと同じように簡単にアニメーションを公開できます。アニメーションは Bodymovin プラグインを使って After Effects から JSON ファイルとしてエクスポートし、パフォーマンスへの影響を最小限に抑えてネイティブにレンダリングします。

Lottie を使用する場面:

  • ピクセル単位の忠実さが求められる、デザイナーが作成したアニメーション
  • 複雑なアニメーションアイコンやマイクロインタラクション
  • ローディングアニメーションや進行状況インジケーター
  • オンボーディングの一連の画面やチュートリアルアニメーション
  • マーケティングアニメーションやプロモーションコンテンツ
  • ファイルサイズを小さくし、拡大縮小にも対応できる GIF/動画の代替

主なメリット:

  • ベクターベース(画質を損なわずに拡大縮小可能)
  • GIF や動画よりファイルサイズを大幅に削減
  • 実行時に編集可能(色、速度、セグメント)
  • After Effects によるデザイナーの完全な制御
  • クロスプラットフォームで一貫したレンダリング
  • インタラクティブな操作(再生、一時停止、シーク、ループ)

主な概念

Lottie 形式の種類

1. JSON Lottie(.json)

  • オリジナルの Lottie 形式
  • Bodymovin プラグインを使って After Effects からエクスポート
  • 人間が読みやすい JSON 構造
  • ファイルサイズが大きい(圧縮されていない)
  • すべてのプラットフォームで広くサポート

2. dotLottie(.lottie)

  • 最新の圧縮形式
  • JSON とアセットを含む ZIP アーカイブ
  • 1 つのファイルで複数のアニメーションとテーマに対応
  • ファイルサイズを削減(最大 90%)
  • 本番環境での使用を推奨
ライブラリの選択肢

lottie-web(オリジナルライブラリ):

import lottie from 'lottie-web';

lottie.loadAnimation({
  container: document.getElementById('lottie-container'),
  renderer: 'svg', // or 'canvas', 'html'
  loop: true,
  autoplay: true,
  path: 'animation.json' // or animationData: jsonData
});

@lottiefiles/dotlottie-web(最新、推奨):

import { DotLottie } from '@lottiefiles/dotlottie-web';

new DotLottie({
  canvas: document.getElementById('canvas'),
  src: 'animation.lottie',
  autoplay: true,
  loop: true
});

@lottiefiles/dotlottie-react(React との統合):

import { DotLottieReact } from '@lottiefiles/dotlottie-react';

<DotLottieReact
  src="animation.lottie"
  loop
  autoplay
  style={{ height: 300 }}
/>

lottie-react(代替の React ラッパー):

import Lottie from 'lottie-react';
import animationData from './animation.json';

<Lottie animationData={animationData} loop={true} />
アニメーションデータの取得元

1. LottieFiles(lottie.host)

  • 100,000 件以上の無料アニメーション
  • URL を直接埋め込み
  • CDN ホスティング

2. ローカルの JSON/dotLottie ファイル

  • アプリケーションにバンドル
  • パフォーマンスの向上(ネットワークリクエストが不要)
  • バージョン管理に適している

3. After Effects からのエクスポート

  • カスタムのデザイナーアニメーション
  • Bodymovin プラグインが必要
  • ファイルサイズを左右するため、エクスポート設定が重要

よく使われるパターン

1. dotLottie-web による基本的な HTML 統合
<!DOCTYPE html>
<html>
<head>
  <style>
    #canvas {
      width: 400px;
      height: 400px;
    }
  </style>
</head>
<body>
  <canvas id="canvas"></canvas>

  <script type="module">
    import { DotLottie } from 'https://cdn.jsdelivr.net/npm/@lottiefiles/dotlottie-web/+esm';

    new DotLottie({
      canvas: document.getElementById('canvas'),
      src: 'https://lottie.host/4db68bbd-31f6-4cd8-84eb-189de081159a/IGmMCqhzpt.lottie',
      autoplay: true,
      loop: true
    });
  </script>
</body>
</html>
2. 操作機能付き React コンポーネント
import React from 'react';
import { DotLottieReact } from '@lottiefiles/dotlottie-react';

const AnimatedButton = () => {
  const [dotLottie, setDotLottie] = React.useState(null);

  const handlePlay = () => dotLottie?.play();
  const handlePause = () => dotLottie?.pause();
  const handleStop = () => dotLottie?.stop();
  const handleSeek = (frame) => dotLottie?.setFrame(frame);

  return (
    <div>
      <DotLottieReact
        src="button-animation.lottie"
        loop
        autoplay={false}
        dotLottieRefCallback={setDotLottie}
        style={{ height: 200 }}
      />

      <div>
        <button onClick={handlePlay}>Play</button>
        <button onClick={handlePause}>Pause</button>
        <button onClick={handleStop}>Stop</button>
        <button onClick={() => handleSeek(30)}>Seek to frame 30</button>
      </div>
    </div>
  );
};
3. イベントリスナーとライフサイクルフック
import React, { useEffect } from 'react';
import { DotLottieReact } from '@lottiefiles/dotlottie-react';

const EventDrivenAnimation = () => {
  const [dotLottie, setDotLottie] = React.useState(null);

  useEffect(() => {
    if (!dotLottie) return;

    const onLoad = () => console.log('Animation loaded');
    const onPlay = () => console.log('Animation started');
    const onPause = () => console.log('Animation paused');
    const onComplete = () => console.log('Animation completed');
    const onFrame = ({ currentFrame }) => console.log('Frame:', currentFrame);

    dotLottie.addEventListener('load', onLoad);
    dotLottie.addEventListener('play', onPlay);
    dotLottie.addEventListener('pause', onPause);
    dotLottie.addEventListener('complete', onComplete);
    dotLottie.addEventListener('frame', onFrame);

    return () => {
      dotLottie.removeEventListener('load', onLoad);
      dotLottie.removeEventListener('play', onPlay);
      dotLottie.removeEventListener('pause', onPause);
      dotLottie.removeEventListener('complete', onComplete);
      dotLottie.removeEventListener('frame', onFrame);
    };
  }, [dotLottie]);

  return (
    <DotLottieReact
      src="animation.lottie"
      loop
      autoplay
      dotLottieRefCallback={setDotLottie}
    />
  );
};
4. lottie-react によるスクロール連動アニメーション
import Lottie from 'lottie-react';
import robotAnimation from './robot.json';

const ScrollAnimation = () => {
  const interactivity = {
    mode: 'scroll',
    actions: [
      {
        visibility: [0, 0.2],
        type: 'stop',
        frames: [0]
      },
      {
        visibility: [0.2, 0.45],
        type: 'seek',
        frames: [0, 45]
      },
      {
        visibility: [0.45, 1.0],
        type: 'loop',
        frames: [45, 60]
      }
    ]
  };

  return (
    <Lottie
      animationData={robotAnimation}
      style={{ height: 300 }}
      interactivity={interactivity}
    />
  );
};
5. ホバーで再生するセグメント
import { useLottie, useLottieInteractivity } from 'lottie-react';
import likeButton from './like-button.json';

const HoverAnimation = () => {
  const lottieObj = useLottie({
    animationData: likeButton
  });

  const Animation = useLottieInteractivity({
    lottieObj,
    mode: 'cursor',
    actions: [
      {
        position: { x: [0, 1], y: [0, 1] },
        type: 'loop',
        frames: [45, 60]
      },
      {
        position: { x: -1, y: -1 },
        type: 'stop',
        frames: [45]
      }
    ]
  });

  return <div style={{ height: 300, border: '2px solid black' }}>{Animation}</div>;
};
6. 複数のアニメーションとテーマへの対応
import { DotLottieReact } from '@lottiefiles/dotlottie-react';
import React, { useState, useEffect } from 'react';

const ThemedAnimation = () => {
  const [dotLottie, setDotLottie] = useState(null);
  const [animations, setAnimations] = useState([]);
  const [themes, setThemes] = useState([]);
  const [currentAnimationId, setCurrentAnimationId] = useState('');
  const [currentThemeId, setCurrentThemeId] = useState('');

  useEffect(() => {
    if (!dotLottie) return;

    const onLoad = () => {
      setAnimations(dotLottie.manifest.animations || []);
      setThemes(dotLottie.manifest.themes || []);
      setCurrentAnimationId(dotLottie.activeAnimationId);
      setCurrentThemeId(dotLottie.activeThemeId);
    };

    dotLottie.addEventListener('load', onLoad);
    return () => dotLottie.removeEventListener('load', onLoad);
  }, [dotLottie]);

  return (
    <div>
      <DotLottieReact
        src="multi-animation.lottie"
        dotLottieRefCallback={setDotLottie}
        animationId={currentAnimationId}
        themeId={currentThemeId}
      />

      {themes.length > 0 && (
        <select value={currentThemeId} onChange={(e) => setCurrentThemeId(e.target.value)}>
          {themes.map((theme) => (
            <option key={theme.id} value={theme.id}>{theme.id}</option>
          ))}
        </select>
      )}

      {animations.length > 0 && (
        <select value={currentAnimationId} onChange={(e) => setCurrentAnimationId(e.target.value)}>
          {animations.map((anim) => (
            <option key={anim.id} value={anim.id}>{anim.id}</option>
          ))}
        </select>
      )}
    </div>
  );
};
7. パフォーマンス向上のための Web Worker(DotLottieWorker)
import { DotLottieWorker } from '@lottiefiles/dotlottie-web';

// Offload animation rendering to a web worker
new DotLottieWorker({
  canvas: document.getElementById('canvas'),
  src: 'heavy-animation.lottie',
  autoplay: true,
  loop: true,
  workerId: 'worker-1' // Group multiple animations by worker
});

// Multiple animations in separate workers
new DotLottieWorker({
  canvas: document.getElementById('canvas-2'),
  src: 'animation-2.lottie',
  autoplay: true,
  loop: true,
  workerId: 'worker-2'
});

統合パターン

GSAP ScrollTrigger との統合
import Lottie from 'lottie-react';
import gsap from 'gsap';
import ScrollTrigger from 'gsap/ScrollTrigger';
import animationData from './animation.json';

gsap.registerPlugin(ScrollTrigger);

const GSAPLottieIntegration = () => {
  const lottieRef = React.useRef();

  React.useEffect(() => {
    const anim = lottieRef.current;
    if (!anim) return;

    // Sync Lottie with scroll
    gsap.to(anim, {
      scrollTrigger: {
        trigger: '#animation-section',
        start: 'top center',
        end: 'bottom center',
        scrub: 1,
        onUpdate: (self) => {
          const frame = Math.floor(self.progress * (anim.totalFrames - 1));
          anim.goToAndStop(frame, true);
        }
      }
    });
  }, []);

  return (
    <div id="animation-section" style={{ height: '200vh' }}>
      <Lottie
        lottieRef={lottieRef}
        animationData={animationData}
        autoplay={false}
        loop={false}
      />
    </div>
  );
};
Framer Motion との統合
import { motion } from 'framer-motion';
import { DotLottieReact } from '@lottiefiles/dotlottie-react';

const MotionLottie = () => {
  return (
    <motion.div
      initial={{ opacity: 0, scale: 0.8 }}
      animate={{ opacity: 1, scale: 1 }}
      transition={{ duration: 0.6 }}
    >
      <DotLottieReact
        src="animation.lottie"
        loop
        autoplay
        style={{ height: 400 }}
      />
    </motion.div>
  );
};
Vue 3 との統合
<script setup>
import { DotLottieVue } from '@lottiefiles/dotlottie-vue';
</script>

<template>
  <DotLottieVue
    style="height: 500px; width: 500px"
    autoplay
    loop
    src="https://path-to-animation.lottie"
  />
</template>
Svelte との統合
<script lang="ts">
  import { DotLottieSvelte } from '@lottiefiles/dotlottie-svelte';
  import type { DotLottie } from '@lottiefiles/dotlottie-svelte';

  let dotLottie: DotLottie | null = null;

  function play() {
    dotLottie?.play();
  }
</script>

<DotLottieSvelte
  src="animation.lottie"
  loop={true}
  autoplay={true}
  dotLottieRefCallback={(ref) => dotLottie = ref}
/>

<button on:click={play}>Play</button>

パフォーマンスの最適化

ファイルサイズの最適化

1. After Effects のエクスポート設定:

  • 「Skip images that aren't used」を有効にする
  • 可能であればフォントの代わりに「Glyphs」を使用する
  • パスを簡略化する(illustrator でポイント数を減らす)
  • 大量のデータを生成するエフェクト(パーティクル、ノイズ)は避ける
  • ベクターレイヤーではなくシェイプレイヤーを使用する

2. 圧縮:

  • 自動圧縮のため、dotLottie 形式(.lottie)を使用する
  • Lottie の最適化ツールで JSON を処理する
  • 不要なメタデータを削除する

3. 遅延読み込み:

const LazyLottie = () => {
  const [shouldLoad, setShouldLoad] = React.useState(false);

  React.useEffect(() => {
    const observer = new IntersectionObserver((entries) => {
      if (entries[0].isIntersecting) {
        setShouldLoad(true);
      }
    });

    observer.observe(document.getElementById('lottie-trigger'));
    return () => observer.disconnect();
  }, []);

  return (
    <div id="lottie-trigger">
      {shouldLoad && <DotLottieReact src="animation.lottie" loop autoplay />}
    </div>
  );
};
実行時のパフォーマンス

1. レンダラーの選択:

// SVG: Best quality, slower for complex animations
// Canvas: Better performance, rasterized
// HTML: Limited support, use only for simple animations

// For complex animations, prefer canvas
new DotLottie({
  canvas: document.getElementById('canvas'),
  src: 'animation.lottie',
  autoplay: true,
  loop: true,
  renderConfig: {
    devicePixelRatio: window.devicePixelRatio || 1
  }
});

2. Web Worker:

// Offload to worker for heavy animations
import { DotLottieWorker } from '@lottiefiles/dotlottie-web';

new DotLottieWorker({
  canvas: document.getElementById('canvas'),
  src: 'heavy-animation.lottie',
  autoplay: true,
  loop: true
});

3. モバイル向けの最適化:

// Reduce quality on mobile
const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);

new DotLottie({
  canvas: document.getElementById('canvas'),
  src: isMobile ? 'animation-low.lottie' : 'animation-high.lottie',
  autoplay: true,
  loop: true,
  renderConfig: {
    devicePixelRatio: isMobile ? 1 : window.devicePixelRatio
  }
});

よくある落とし穴

1. 不適切なクリーンアップによるメモリリーク

問題: コンポーネントのアンマウント時に Lottie インスタンスを破棄していません。

解決策:

const SafeAnimation = () => {
  const [dotLottie, setDotLottie] = React.useState(null);

  React.useEffect(() => {
    return () => {
      // Always destroy instance on unmount
      dotLottie?.destroy();
    };
  }, [dotLottie]);

  return <DotLottieReact src="animation.lottie" dotLottieRefCallback={setDotLottie} />;
};
2. イベントリスナーのクリーンアップ

問題: イベントリスナーが削除されず、ハンドラーが複数回実行されます。

解決策:

useEffect(() => {
  if (!dotLottie) return;

  const handleComplete = () => console.log('Complete');
  dotLottie.addEventListener('complete', handleComplete);

  // MUST return cleanup function
  return () => {
    dotLottie.removeEventListener('complete', handleComplete);
  };
}, [dotLottie]);
3. ファイルサイズが大きい

問題: シンプルなアニメーションでも、エクスポートした JSON ファイルが 500KB 以上になります。

解決策:

  • After Effects のコンポジションを簡素化します(レイヤーやキーフレームを減らします)
  • 圧縮には dotLottie 形式を使用します
  • Bodymovin のエクスポート設定を確認します(不要であれば「Include expressions」を無効にします)
  • エクスポート前に未使用のアセットを削除します
  • Lottie の最適化ツールを使用します:https://lottiefiles.com/tools/lottie-editor
4. アニメーションのパフォーマンスに関する問題

問題: アニメーションがカクついたり、フレームがドロップしたりします。

解決策:

  • SVG から Canvas レンダラーに切り替えます
  • Web Worker でのレンダリングには DotLottieWorker を使用します
  • After Effects での複雑さを軽減します(レイヤーを減らし、シェイプをシンプルにします)
  • モバイルでは devicePixelRatio を下げます
  • 多くのプロパティを同時にアニメーションさせないようにします
5. パス/URL の参照が正しくない

問題: CORS またはパスの誤りにより、アニメーションが読み込まれません。

解決策:

// Use animationData for local imports (best for bundled apps)
import animationData from './animation.json';
<Lottie animationData={animationData} />

// OR use path for external URLs (requires CORS headers)
<DotLottieReact src="https://example.com/animation.lottie" />

// For Next.js, place in public/ folder
<DotLottieReact src="/animations/animation.lottie" />
6. After Effects のエクスポート互換性

問題: After Effects の一部の機能は Lottie にエクスポートできません。

サポートされていない機能:

  • レイヤーエフェクト(ドロップシャドウ、グロー) - 代わりにシェイプレイヤーを使用します
  • ブレンドモード(サポートは限定的です)
  • 3D レイヤー
  • エクスプレッション(一部サポート)
  • トラックマット(一部サポート)

解決策:

  • 早い段階からこまめにエクスポートをテストします
  • エクスポート前に LottieFiles のプレビューを使用します
  • Bodymovin の互換性を確認します:https://airbnb.io/lottie/#/supported-features
  • 可能であれば、エフェクトをシェイプに変換します

リソース

このスキルには、以下が含まれています。

scripts/
  • generate_lottie_component.py - React/Vue/Svelte の Lottie コンポーネントのボイラープレートを生成します
  • optimize_lottie.py - Lottie の JSON ファイルサイズを最適化します
references/
  • api_reference.md - lottie-web、lottie-react、dotlottie-web の完全な API ドキュメント
  • after_effects_export.md - After Effects からアニメーションをエクスポートするためのガイド
  • performance_guide.md - パフォーマンスを最適化するための詳細な方法
assets/
  • starter_lottie/ - Lottie のサンプルを含む、React + Vite の完全なスターターテンプレート
  • examples/ - 実際の Lottie アニメーションのパターンとユースケース

関連スキル

  • gsap-scrolltrigger - ページのスクロールに同期する、スクロール駆動の Lottie アニメーション向け
  • motion-framer - Lottie を包むレイアウトアニメーションに Framer Motion を組み合わせる場合
  • animated-component-libraries - Lottie アニメーションを含むことがある、事前構築済みコンポーネント
  • threejs-webgl - Lottie の 2D 機能を超える 3D アニメーション向け
  • react-three-fiber - 複雑な 3D アニメーションシーン向けの代替手段

コメント