Communitygithub.com

billel-chami/video-to-gsap

ビデオ録画、GIF、またはプロトタイプアニメーション(例:Figmaプロトタイプ)が提供された場合に使用します。モーションの振り付けをタイミング、イージングカーブ、空間軌跡、スタガーに分解し、@gsap/react と useGSAP を使用して Next.js 16 でハードウェアアクセラレーションされ、メモリリークのない GSAP アニメーションを実装します。

video-to-gsap とは?

このスキルは、ビデオ、GIF、またはFigmaプロトタイプのモーションクリップからアニメーションの振り付けを抽出し、Next.js 16 でパフォーマンスの高い GSAP アニメーションとして実装するためのプロトコルを提供します。タイミング、イージングカーブ、スタガー、空間軌跡を体系的に分析し、`transform` と `opacity` のみをアニメートすることでハードウェアアクセラレーションを強制し、メモリリークを防ぐために `@gsap/react` の `useGSAP` フックをスコープ付きで使用します。また、`autoAlpha` による FOUC(スタイル未適用コンテンツのフラッシュ)の防止、`clearProps` によるアニメーション後のインラインスタイルのクリーンアップ、`prefers-reduced-motion` メディアクエリによるアクセシビリティ対応など、本番環境に即した実装パターンを提供します。このスキルは、Claude Code、Cursor、Codex などの AI エージェントが、高品質でプロフェッショナルな Web アニメーションを作成する際のガイドとして設計されています。

対応~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/billel-chami/nextjs-medusa-handbook/tree/HEAD/.agents/skills/video-to-gsap

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

ビデオ&プロトタイプモーション抽出 (video-to-gsap)

1. 目的とトリガー

流暢なマイクロインタラクションと映画的なモーションは、ハイエンドなコマース体験を差別化します。しかし、Webアニメーションの実装が不適切だと、スレッドのブロッキング、フレームドロップ(ジャンク)、メモリリーク、INP(Interaction to Next Paint)の低下を引き起こします。このスキルは、滑らかな60/120 FPSアニメーションの抽出と実装を統制します。

トリガー:

  • ユーザーがビデオクリップ、GIF、またはFigmaモーションプロトタイプを提供した場合。
  • カートスライドオーバー、ページトランジション、アコーディオン展開、プロダクトカードホバー、チェックアウト完了の祝福をアニメーション化する場合。
  • ScrollTriggerを使用したスクロール駆動アニメーションを作成する場合。

2. モーション分解プロトコル

モーションクリップを分析する際は、体系的に以下を特定します:

  1. 振り付けシーケンス:
    • ステージング / トリガー: どのアクションがモーションを開始するか(ホバー、スクロール、ルート変更、クリック)?
    • 予備動作: 主要モーションの前に微妙な逆方向の動きがあるか?
    • アクションと移動: どの要素が、どの方向に、どの距離(px、rem、%)動くか?
    • 落ち着きとフォロースルー: オーバーシュート(スプリング/エラスティック)するか、スムーズに減速するか(power3.out、expo.out)?
  2. タイミング分解:
    • 各要素の持続時間(例:ドロワーエントリー: 450ms、背景フェード: 300ms)。
    • スタガーされた子要素間のスタガーオフセット(例:プロダクトグリッドカード: 0.06s スタガー)。
  3. イージングシグネチャ:
    • リニア: 連続ループ専用(例:マーキー)。
    • イーズアウト(power2.out、expo.out): UIエントランス用(高速エントリー、緩やかなセトリング)。
    • イーズイン(power2.in): UIエグジット用(画面外に加速)。
    • イーズインアウト(power3.inOut): ビュー内に留まる状態変換用。

3. パフォーマンスとハードウェアアクセラレーション基準

ルール1: コンポジットプロパティのみをアニメーション化する

  • 許可: transform(x、y、xPercent、yPercent、scale、rotation、skew)および opacity(または GSAP autoAlpha)。
  • 厳格に禁止: レイアウトまたはペイントプロパティ(width、height、top、left、right、bottom、margin、padding、border-width)のアニメーション化。これらはブラウザのCPUに毎フレームレイアウトジオメトリの再計算とピクセルの再描画を強制し、INP低下とフレームドロップを引き起こします。

ルール2: スコープ付き useGSAP によるゼロメモリリーク

  • 常に公式の @gsap/react パッケージと useGSAP フックを使用します。
  • scope コンテナrefを提供します。内部のすべてのセレクタは自動的にスコープ化され、すべてのタイムライン、トゥイーン、ScrollTriggerインスタンスは、コンポーネントのアンマウント時にクリーンに元に戻され、killされます。
  • これにより、シングルページアプリケーションやReact 19の高速リフレッシュサイクルにおけるゾンビイベントリスナーとメモリ保持を防ぎます。

ルール3: FOUC(スタイル未適用コンテンツのフラッシュ)の排除

  • opacity の代わりに autoAlpha を使用します。autoAlpha は、不透明度が0になると visibility: hidden を設定し、ハイドレーション前のゴーストクリックやレンダリングフラッシュを防ぎます。
  • または、CSSのデフォルトの非表示状態を宣言し、gsap.fromTo でそれらを表示します。

4. プロダクション実装ブループリント

"use client";

import { useRef } from "react";
import gsap from "gsap";
import { useGSAP } from "@gsap/react";
import { ScrollTrigger } from "gsap/ScrollTrigger";

// プラグインが安全に登録されていることを確認
if (typeof window !== "undefined") {
  gsap.registerPlugin(useGSAP, ScrollTrigger);
}

interface ProductShowcaseProps {
  readonly items: Array<{ id: string; title: string; price: string }>;
}

export function ProductShowcase({ items }: ProductShowcaseProps) {
  const containerRef = useRef<HTMLDivElement | null>(null);

  useGSAP(
    () => {
      // ハードウェアアクセラレーションによるエントランスタイムライン
      const tl = gsap.timeline({
        defaults: {
          ease: "expo.out",
          duration: 0.8,
        },
      });

      tl.from(".showcase-header", {
        autoAlpha: 0,
        y: 30,
        clearProps: "all", // アニメーション後のインラインスタイルをクリーンアップ
      }).from(
        ".product-card",
        {
          autoAlpha: 0,
          y: 40,
          scale: 0.96,
          stagger: 0.08,
          duration: 0.7,
          clearProps: "transform,opacity",
        },
        "-=0.4" // シームレスなオーバーラップ
      );
    },
    { scope: containerRef } // スコープ化されたクリーンアップ境界
  );

  return (
    <section ref={containerRef} className="w-full py-16 px-6">
      <div className="showcase-header max-w-4xl mx-auto text-center mb-12">
        <h2 className="text-h1 font-bold text-content-primary">Featured Collection</h2>
      </div>

      <div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-7xl mx-auto">
        {items.map((item) => (
          <article
            key={item.id}
            className="product-card will-change-transform bg-surface-elevated rounded-lg p-6 border border-border-subtle"
          >
            <h3 className="text-h3 font-semibold text-content-primary">{item.title}</h3>
            <p className="text-content-secondary mt-2">{item.price}</p>
          </article>
        ))}
      </div>
    </section>
  );
}

5. モーション軽減の準拠

モーションを軽減したいユーザーの設定を常に尊重します:

const { contextSafe } = useGSAP({ scope: containerRef });

// アクセシビリティ設定を確認
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

if (prefersReducedMotion) {
  // アニメーションなしで最終静止状態を即座にレンダリング
  gsap.set([".showcase-header", ".product-card"], { autoAlpha: 1, y: 0, scale: 1 });
  return;
}

関連スキル