Communitygithub.com

billel-chami/video-to-gsap

Utilisez cette compétence lorsqu'une vidéo, un GIF ou une animation prototype (ex. prototype Figma) vous est fournie. Déconstruit la chorégraphie de mouvement en timing, courbes d'assouplissement, trajectoires spatiales et décalages, et implémente des animations GSAP accélérées matériellement et sans fuite mémoire dans Next.js 16 avec @gsap/react et useGSAP.

Qu'est-ce que video-to-gsap ?

Cette compétence permet d'analyser une séquence vidéo, un GIF ou un prototype d'animation (comme un prototype Figma) pour en extraire la chorégraphie de mouvement : timing, courbes d'assouplissement (easing), trajectoires spatiales et décalages (stagger). Elle génère ensuite des animations GSAP performantes et sans fuite mémoire dans un projet Next.js 16, en utilisant le package officiel @gsap/react et le hook useGSAP. Idéale pour les développeurs souhaitant reproduire des micro-interactions fluides (hover, transitions de page, accordéons, etc.) tout en respectant les standards de performance (60/120 FPS), en évitant les fuites mémoire grâce à un nettoyage automatique des timelines et en respectant les préférences de mouvement réduit des utilisateurs.

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

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Extraction de mouvement de vidéo & prototype (video-to-gsap)

1. Objectif & Déclencheurs

Les micro-interactions fluides et les mouvements cinématiques différencient les expériences de commerce haut de gamme. Cependant, des animations web mal implémentées provoquent des blocages de thread, des pertes d'images (jank), des fuites mémoire et une mauvaise Interaction to Next Paint (INP). Cette compétence régit l'extraction et l'implémentation d'animations fluides à 60/120 FPS.

Déclencheurs :

  • Lorsque l'utilisateur fournit un clip vidéo, un GIF ou un prototype de mouvement Figma.
  • Lors de l'animation de paniers coulissants, de transitions de pages, d'extensions d'accordéons, de survols de cartes produits ou de célébrations de finalisation de commande.
  • Lors de la création d'animations pilotées par le défilement avec ScrollTrigger.

2. Protocole de déconstruction du mouvement

Lors de l'analyse d'un clip de mouvement, identifiez systématiquement :

  1. La séquence chorégraphique :
    • Mise en scène / Déclencheur : Quelle action déclenche le mouvement (survol, défilement, changement de route, clic) ?
    • Anticipation : Y a-t-il un contre-mouvement subtil avant le mouvement principal ?
    • Action et déplacement : Quels éléments se déplacent, dans quelles directions, sur quelle distance (px, rem ou %) ?
    • Stabilisation et suivi : Le mouvement dépasse-t-il sa cible (ressort/élastique) ou ralentit-il en douceur (power3.out, expo.out) ?
  2. Analyse temporelle :
    • Durée de chaque élément (ex. entrée du tiroir : 450ms, fondu d'arrière-plan : 300ms).
    • Décalage entre les enfants décalés (ex. cartes d'une grille produit : 0.06s de décalage).
  3. Signature d'assouplissement :
    • Linéaire : strictement pour les boucles continues (ex. marquee).
    • Ease-out (power2.out, expo.out) : pour les entrées d'interface (entrée rapide, stabilisation douce).
    • Ease-in (power2.in) : pour les sorties d'interface (accélération vers la sortie).
    • Ease-in-out (power3.inOut) : pour les transformations d'état restant dans la vue.

3. Normes de performance et d'accélération matérielle

Règle 1 : Animer uniquement les propriétés composites

  • Autorisé : transform (x, y, xPercent, yPercent, scale, rotation, skew) et opacity (ou GSAP autoAlpha).
  • Strictement interdit : Animer les propriétés de layout ou de peinture (width, height, top, left, right, bottom, margin, padding, border-width). Celles-ci forcent le CPU du navigateur à recalculer la géométrie de mise en page et à repeindre les pixels à chaque image, entraînant une dégradation de l'INP et des pertes d'images.

Règle 2 : Zéro fuite mémoire avec useGSAP limité à un scope

  • Utilisez toujours le package officiel @gsap/react et le hook useGSAP.
  • Fournissez une référence scope conteneur. Tous les sélecteurs à l'intérieur seront automatiquement limités, et toutes les timelines, tweens et instances ScrollTrigger seront proprement annulées et tuées lorsque le composant se démonte.
  • Cela empêche les écouteurs d'événements zombies et la rétention mémoire dans les applications monopages et les cycles de rechargement rapide de React 19.

Règle 3 : Éliminer le FOUC (Flash de contenu non stylisé)

  • Utilisez autoAlpha au lieu de opacity. autoAlpha définit visibility: hidden lorsque l'opacité atteint 0, empêchant les clics fantômes et les flashs de rendu avant l'hydratation.
  • Alternativement, déclarez des états cachés par défaut CSS et révélez-les avec gsap.fromTo.

4. Plan de mise en œuvre en production

"use client";

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

// Assurez-vous que les plugins sont enregistrés de manière sécurisée
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(
    () => {
      // Timeline d'entrée accélérée matériellement
      const tl = gsap.timeline({
        defaults: {
          ease: "expo.out",
          duration: 0.8,
        },
      });

      tl.from(".showcase-header", {
        autoAlpha: 0,
        y: 30,
        clearProps: "all", // Nettoie les styles en ligne après l'animation
      }).from(
        ".product-card",
        {
          autoAlpha: 0,
          y: 40,
          scale: 0.96,
          stagger: 0.08,
          duration: 0.7,
          clearProps: "transform,opacity",
        },
        "-=0.4" // Chevauchement transparent
      );
    },
    { scope: containerRef } // Limite de nettoyage basée sur le scope
  );

  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">Collection vedette</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. Conformité au mouvement réduit

Respectez toujours les utilisateurs qui préfèrent un mouvement réduit :

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

// Vérifier la préférence d'accessibilité
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;

if (prefersReducedMotion) {
  // Afficher instantanément l'état final de repos sans animation
  gsap.set([".showcase-header", ".product-card"], { autoAlpha: 1, y: 0, scale: 1 });
  return;
}

Skills associés