Animation12 de lecture1 novembre 2024

Créer des animations dignes d'Awwwards avec Framer Motion

Guide complet pour maîtriser Framer Motion et créer des animations premium qui impressionnent. De la théorie à la pratique avec des exemples concrets.

Créer des animations dignes d'Awwwards avec Framer Motion

Introduction

Les animations web ne sont plus un luxe, elles sont devenues essentielles pour créer des expériences utilisateur mémorables. Framer Motion est la bibliothèque de référence pour React, et voici comment en tirer le maximum.

Les fondamentaux

Le composant motion

Tout commence par le composant motion. Il transforme n'importe quel élément HTML en élément animable :

import { motion } from 'framer-motion'

function FadeIn() {
  return (
    <motion.div
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.6 }}
    >
      Contenu animé
    </motion.div>
  )
}

Les propriétés clés

  • initial : État de départ
  • animate : État final
  • exit : État de sortie (avec AnimatePresence)
  • transition : Configuration de l'animation
  • whileHover / whileTap : États interactifs

Animations avancées

Variants : orchestrer des animations complexes

Les variants permettent de créer des animations coordonnées entre parents et enfants :

const containerVariants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.1, // Délai entre chaque enfant
    },
  },
}

const itemVariants = {
  hidden: { opacity: 0, y: 20 },
  visible: { opacity: 1, y: 0 },
}

function StaggeredList({ items }) {
  return (
    <motion.ul
      variants={containerVariants}
      initial="hidden"
      animate="visible"
    >
      {items.map((item) => (
        <motion.li key={item.id} variants={itemVariants}>
          {item.name}
        </motion.li>
      ))}
    </motion.ul>
  )
}

Animations au scroll avec useScroll

Créez des animations liées au défilement :

import { motion, useScroll, useTransform } from 'framer-motion'

function ParallaxHero() {
  const { scrollYProgress } = useScroll()

  const y = useTransform(scrollYProgress, [0, 1], [0, -200])
  const opacity = useTransform(scrollYProgress, [0, 0.5], [1, 0])
  const scale = useTransform(scrollYProgress, [0, 0.5], [1, 0.8])

  return (
    <motion.div style={{ y, opacity, scale }}>
      <h1>Hero parallax</h1>
    </motion.div>
  )
}

Spring physics pour des animations naturelles

Les animations spring imitent la physique réelle :

<motion.div
  animate={{ x: 100 }}
  transition={{
    type: "spring",
    stiffness: 100,  // Rigidité du ressort
    damping: 10,     // Amortissement
    mass: 1,         // Masse de l'élément
  }}
/>

Patterns Awwwards

1. Text reveal character by character

const text = "Hello World"

function TextReveal() {
  return (
    <motion.div
      initial="hidden"
      animate="visible"
      variants={{
        visible: { transition: { staggerChildren: 0.05 } },
      }}
    >
      {text.split("").map((char, i) => (
        <motion.span
          key={i}
          variants={{
            hidden: { opacity: 0, y: 50 },
            visible: { opacity: 1, y: 0 },
          }}
        >
          {char}
        </motion.span>
      ))}
    </motion.div>
  )
}

2. Magnetic buttons

function MagneticButton({ children }) {
  const ref = useRef(null)
  const [position, setPosition] = useState({ x: 0, y: 0 })

  const handleMouse = (e) => {
    const { clientX, clientY } = e
    const { left, top, width, height } = ref.current.getBoundingClientRect()
    const x = (clientX - left - width / 2) * 0.3
    const y = (clientY - top - height / 2) * 0.3
    setPosition({ x, y })
  }

  const reset = () => setPosition({ x: 0, y: 0 })

  return (
    <motion.button
      ref={ref}
      onMouseMove={handleMouse}
      onMouseLeave={reset}
      animate={position}
      transition={{ type: "spring", stiffness: 150, damping: 15 }}
    >
      {children}
    </motion.button>
  )
}

3. Page transitions

import { AnimatePresence } from 'framer-motion'

function Layout({ children }) {
  return (
    <AnimatePresence mode="wait">
      <motion.main
        key={pathname}
        initial={{ opacity: 0, y: 20 }}
        animate={{ opacity: 1, y: 0 }}
        exit={{ opacity: 0, y: -20 }}
        transition={{ duration: 0.3 }}
      >
        {children}
      </motion.main>
    </AnimatePresence>
  )
}

Performance

Optimisations essentielles

  1. Utilisez transform et opacity - Ces propriétés sont optimisées par le GPU
  2. Évitez les re-renders - Utilisez useMotionValue pour les valeurs dynamiques
  3. Layout animations - Utilisez layoutId pour des transitions fluides entre états
// ❌ Mauvais - cause des re-renders
const [x, setX] = useState(0)
<motion.div animate={{ x }} />

// ✅ Bon - pas de re-render
const x = useMotionValue(0)
<motion.div style={{ x }} />

Conclusion

Framer Motion offre des possibilités infinies pour créer des expériences web exceptionnelles. La clé est de commencer simple et d'itérer progressivement vers des animations plus complexes.

N'oubliez pas : une bonne animation améliore l'UX, une mauvaise la dégrade. Testez toujours sur différents appareils et respectez les préférences prefers-reduced-motion.

#Framer Motion#React#Animation#UX
Partager cet article