Skip to content

Latest commit

 

History

History
985 lines (748 loc) · 36.6 KB

animations_css_js.md

File metadata and controls

985 lines (748 loc) · 36.6 KB

Animations CSS / JS

Transformations CSS

Parmi toutes les propriétés pouvant faire l'objet de transitions ou d'animations, transform et opacity sont les deux propriétés les plus utilisées. Animer seulement ces propriétés permet d'avoir des animations performantes.

Utiliser la propriété will-change en CSS ou en javaScript sur des éléments qui vont nécessairement faire l'objet d'animation ou de transitions permet au navigateur d'optimiser ses performances. Cette propriété ne doit pas être utilisée systématiquement mais uniquement en cas de problème de performance.

Transformations 2D

Nous disposons maintenant de propriétés nous permettant de faire subir des transformations 2D aux éléments HTML. L’ensemble de ces transformations ont lieu après que la page soit rendue et n’influencent donc pas le rendu de la page.

Translate

Effectue une translation, soit sur l’axe horizontal, soit sur l’axe vertical, soit sur les deux. Les valeurs spécifiées peuvent être positives ou négatives.

.myElement {
  transform: translateX(100px);
}

.myElement {
  transform: translateY(20%);
}

.myElement {
  transform: translate(100px, 20%);
}

Scale

Effectue une mise à l’échelle. Cette mise à l’échelle peut concerné la hauteur ou la largeur d’un élément ou les deux. L’argument ne prend pas ici d’unité de mesure, il s’agit d’un ratio par rapport à la taille par défaut de l’élément.

.myElement {
  transform: scaleX(1.5);
}

.myElement {
  transform: scaleY(1.5);
}

.myElement {
  transform: scale(1.5);
}

Rotate

Effectue une rotation. Les valeurs spécifiées peuvent être positives ou négatives. Ces valeurs peuvent être spécifiées en degrés ou en nombre de tours

.myElement {
  transform: rotate(2turn);
}

.myElement {
  transform: rotate(45deg);
}

Skew

Effectue une distorsion de type “skew” spécifiée en degrés. Celle-ci peut être appliquée selon les axes horizontaux ou verticaux ou encore selon les deux à la fois. Les valeurs spécifiées peuvent être positives ou négatives.

.myElement {
  transform: skewY(30deg);
}

Transform-origin

Par défaut, ces transformations prennent généralement le coin supérieur droit de la bounding-box de l’élément comme point de référence. La propriété transform-origin permet de modifier ce point de référence.

.myElement {
  transform-origin: 0 50%;
}

Note: Firefox ne supporte pas toujours bien la propriété transform-origin lorsqu'elle est exprimée en pourcentages et lorsque les transformations sont appliqués à des fichiers SVG. Pour contourner ce problème, vous pouvez la spécifier en pixels par exemple.

Chaining

Nous pouvons également combiner différentes transformation en les chaînant et en les séparant par un espace. Les navigateurs appliquent ces diverses transformations successivement en commençant par la gauche.

.myElement {
  transform: rotate(45deg) scale(2);
}

Exercice: expérimenter avec les transformation 2D en :hover

Transformations 3D

L'une des notions les plus importantes à comprendre est celle de perspective. Chris Coyier vous en donne un bon aperçu sur CSS Tricks.

En bref, la perspective est la profondeur de l'axe Z, la distance entre un objet situé sur celui-ci et l'utilisateur. Plus ce chiffre est petit, plus la perspective est importante. Plus cette valeur est grande, plus l'effet sera subtil.

La perspective peut être spécifiées de deux façons:

Via la propriété transform directement sur l'élément concerné

Dans ce cas, chaque élément concerné possède son propre "vanishing point".

.myElement {
  transform: perspective(300px) rotateY(20deg);
}

Si vous utilisez transform: perspective(xxx) sur un élément, veillez bien à l'utiliser avant d'avoir spécifié votre propriété transform dans votre CSS.

Ne fonctionne pas:

.myElement {
  transform: rotateY(20deg) perspective(300px);
}

Fonctionne:

.myElement {
  transform: perspective(300px) rotateY(20deg);
}

Via la propriété perspective sur l'élément parent

Dans ce cas, cela affecte l'ensemble des enfants du parent, qui partagent alors tous le même "vanishing point".

.myParentElement {
  perspective: 300px;
}

Attention, la perspective n'affecte que les enfants directs. Si vous devez utiliser la même perspective pour des éléments qui sont des descendants plus lointains, vous pouvez utiliser la propriété transform-style qui peut prendre les valeurs flat ou preserve-3d. La seconde valeur permet d'étendre le contexte 3D à tous les descendants du parent auquel la perpective aura été appliquée.

La plupart des transformations 2D ont leur équivalent en 3D. Vous retrouverez également la propriété transform-origin vue plus haut.

.myElement {
  transform: rotateX(50deg);
}

.myElement {
  transform: translateZ(50px);
}

.myElement {
  transform: scaleZ(200px);
}

Il existe également des notations courtes qui requièrent des valeurs pour les trois dimensions:

.myElement {
  transform: translate3d([x], [y], [z]);
  transform: scale3d([x], [y], [z]);
  transform: rotate3d([x], [y], [z], [angle]);
}

Avec rotate3d, vous spécifiez simplement quels axes de rotation sont activés (valeurs 0 ou 1) et vous définissez ensuite l'angle à appliquer.

Avec les transformations 3D, vous pouvez placer certains éléments de telle façon que leur "avant" ne fasse plus face à l'écran. Par exemple avec une rotation:

.myElement {
  transform: rotateY(180deg);
}

Dans ce cas la propriété backface-visibility permet de gérer la visibilité des faces d'un élément lorsqu'elles ne font pas face à l'écran. Les valeurs possibles sont visible et hidden.

.myElement {
  transform: rotateY(180deg);
  backface-visibility: visible;
  /*backface-visibility:hidden;*/
}

Transitions en CSS

Les transitions permettent au navigateur de gérer la transition entre deux états d’un élément spécifiés par CSS. Voici une liste des propriétés CSS pouvant être animées.

Les transitions CSS sont souvent utilisées pour "lisser" les transitions entre deux états d'éléments d'interface: boutons (default et hover ou touch), apparitions successives des éléments d'un menu, etc.

Les propriétés permettant de gérer les transitions sont transition-property, transition-duration, transition-delay, transition-timing-function.

.myElement {
  transition-property: background-color;
  transition-duration: 0.2s;
  transition-delay: 0.1s;
  transition-timing-function: ease-out;
}

Il est également possible d’utiliser une notation courte:

.myElement {
  transition: all 2s 0.2s ease-out;
}

Vous pouvez éventuellement combiner diverses transitions, en notation étendue comme en notation courte.

.myElement {
  transition-property: background-color, transform;
  transition-duration: 0.25s, 0.5s;
  transition-delay: 0.1s, 0.2s;
  transition-timing-function: ease-out, ease-in;
}

ou

.myElement {
  transition: background-color 0.25s 0.1s ease-in, transform 0.5s 0.2s ease-out;
}

Note: la propriété transition-timing-function peut également être exprimée avec des courbes de Bezier pour plus de précision. Lea Verou a réalisé un outil en ligne vous permettant de les calculer et de les visualiser facilement. A voir aussi, Caeser par Matthew Lein ou tout simplement les outils de dévelopement dans Chrome ou Firefox.

Exercice: expérimenter avec les transitions en :hover

Les transitions sont également souvent déclenchées à l'aide de JavaScript. Pour cela, il vous faudra sélectionner vos éléments (querySelector, querySelectorAll) et ajouter ou supprimer des classes dans votre HTML (API classList) lors du déclenchement d'un événement (eventListener), par exemple un click.

Voyons ensemble comment créer un menu de navigation déclenché par un click sur une icône "hamburger". Ce menu va venir "pousser" le contenu de la page.

Exercice: créer un menu responsive avec déclenchement au click (querySelector, querySelectorAll, eventListener, classList)

Les transitions CSS sont faciles à mettre en oeuvre et à manipuler via JavaScript. Elles permettent de réaliser une certaine palette d'effets mais elles ont également leurs limitations:

  • les transitions se font toujours d'un état A vers un état B, sans étapes intermédiaires. Pour contrôler plus finement les étapes, il faut se tourner vers les animations CSS.
  • les transitions ne peuvent pas effectuer de loop ou d'itération. Si vous souhaitez une animation en boucle ou ayant plusieurs itérations, il faut vous tourner vers les animations.
  • les transitions ne sont pas réutilisables, les animations peuvent être appliquées à plusieurs éléments une fois définies.

Animations en CSS

Voyons maintenant comment créer de véritables animations en CSS. Le processus comporte deux étapes distinctes.

  1. Définir votre animation
  2. L'assigner à un ou plusieurs éléments HTML

Définir vos animations avec @keyframes

Vous pouvez nommer votre animation et décrire les étapes qui la composent en utilisant l'élément @keyframes. Celle-ci défini les propriétés qui doivent être modifiées et à quel moment elles doivent l'être dans le déroulement de votre animation.

Les étapes de votre animations peuvent soit être décrites à l'aide des mots-clés from et to, soit à l'aide de valeurs en pourcentage. Ces dernières sont utiles si vous avez plus de deux étapes et/ou si vous avez besoin d'une progression non-linéaire.

@keyframes move {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(400px);
  }
}
@keyframes move {
  0% {
    transform: translateX(0);
  }
  20% {
    transform: translateX(100px);
  }
  100% {
    transform: translateX(400px);
  }
}

Note: si vous ne spécifiez pas de de keyframes à 0% ou 100%, les styles originaux appliqués à votre élément seront utilisés.

Assigner l'animation à un ou plusieurs éléments HTML

Vous allez maintenant assigner cette animation à un élément HTML et en définir les caractéristiques pour cet élément. Cela se fait à l'aide des propriétés suivantes

  • animation-name: spécifie le nom de l'animation à appliquer (celui que vous avez spécifié dans votre élément @keyframes)
  • animation-duration: défini la durée de l'animation. Cette propriété est exprimée en secondes s ou en milisecondes ms.
  • animation-timing-function: défini le easing de votre animation: ease-in, ease-out, linear ou encore cubic-bezier(0.1, 0.7, 1.0, 0.1) sont des valeurs possibles. Par défaut, la valeur est ease.
  • animation-iteration-count: défini le nombre de fois que l'animation doit être effectuée. Par défaut, la valeur est 1. Cette valeur peut également être définie comme infinite.

@keyframes, animation-name et animation-duration sont suffisants mais il vaut mieux toujours définir explicitement les deux autres.

Exercice: réaliser plusieurs nuages qui traversent l'écran (une seule animation @keyframes) et expérimenter avec les diverses propriétés vues ci-dessus. Attention, des vendor-prefixes sont encore nécessaires pour les navigateurs webkit tels que chrome ou Safari. Chris Coyier vous en détaille l'utilisation dans un article sur CSS-Tricks

Différentes autres propriétés

animation-delay

animation-delay défini le délai avant lequel l'animation se déclenche. Spécifié en secondes s ou milisecondes ms.

animation-fill-mode

animation-fill-mode défini la manière dont se comporte l'élément animé une fois l'animation terminée. Les valeurs possibles sont:

  • none: l'élément retrouve ses caractéristiques originales une fois l'animation terminée
  • forwards: l'élément conserve les caractéristiques de la dernière frame de l'animation
  • backwards: l'élément possède les caractéristiques de la première frame de l'animation pendant la durée de animation-delay. Cette valeur est donc particulièrement utile en travaillant avec des délais.
  • both: combine les effets de backwards et forwards.

Exercice: expérimenter avec les diverses valeurs de animation-fill-mode.

animation-direction

animation-direction défini la direction dans laquelle se déroule l'animation.

  • normal: l'animation se déroule de la première frame définie jusqu'à la dernière. C'est la valeur par défaut.
  • reverse: l'animation se déroule de la dernière frame définie jusqu'à la première.
  • alternate: ne peut être utilisé que lorsque votre propriété animation-count est supérieure à 1. La première fois que l'animation est exécutée, elle se déroule en mode normal, la seconde fois en mode reverse, etc.
  • alternate-reverse: identique à alternate hormis que l'animation se déroule d'abord en mode reverse.

Exercice: expérimenter avec les diverses valeurs de animation-direction.

Notation courte et chaining

Une notation courte existe évidemment pour appliquer vos animations à un élément HTML.

animation: myAnimation 0.5s ease-in 1s 3;

Dans l'ordre: <animation-name> <animation-duration> <animation-timing-function> <animation-delay> <animation-iteration-count>.

Il est également possible de chaîner plusieurs animations sur un même élément.

animation: myAnimation 1s ease-in-out 2s 4, myOtherAnimation 4s ease-out 2s;

Exercices

  • Voitures roulant à travers l'écran à différentes vitesses et dans différents sens
  • Animation image par image avec un sprite et steps. La marche à suivre est ici de réaliser un sprite. Créer une animations @keyframes allant du haut du sprite au bas du sprite à l'aide background-position. Enfin, spécifier un nombre d'étapes correspondant aux nombre d'images fixes dans le sprite.
@keyframes fly {
  /* keyframe implicite: background-position:0 0; */

  100% {
    background-position: 0 -400px;
  }
}

.bird {
  position: absolute;
  top: 20px;
  left: 20px;
  width: 200px;
  height: 100px;
  background: url(../img/bird_sprite.png) 0 0 no-repeat;

  animation: fly 0.5s steps(4) infinite;
}

Démarrer et arrêter une animation avec animation-play-state

Vous pouvez facilement définir vos animations, les assigner à vos éléments HTML et en contrôler l'état avec animation-play-state qui peut avoir deux valeurs: running (default) et paused.

Ces propriétés peuvent être modifiées facilement en CSS avec des pseudo-classes comme :hover ou en utilisant JavaScript (querySelector, querySelectorAll, addEventListener et classList).

Exemple: animation-play-state et :hover

@keyframes spin {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(1turn);
  }
}

.windmill {
  animation: spin 5s linear infinite;
  animation-play-state: paused;
}

.windmill:hover {
  animation-play-state: running;
}

Exemple: animation-play-state et classes manipulées via JavaScript.

@keyframes spin {
  0% {
    transform: rotate(0);
  }
  100% {
    transform: rotate(1turn);
  }
}

.sticker {
  animation: spin 5s linear infinite;
  animation-play-state: paused;
}

.sticker.is-animated {
  animation-play-state: running;
}

Animations liées au scroll: scroll et view timelines

Les animations CSS peuvent être liées au scroll de deux façons via CSS:

  • scroll progress timeline: la timeline de l'animation est directement connectée au défilement (scroll) vertical ou horizontal d'un container
  • view progress timeline: l'animation est directement liée à la position d'un élément dans le défilement (scroll) d'un container

En attendant le dévelopement d'outils dédiés dans les outiuls de dévelopement des navigateurs, des outils de visualisation permettent comprendre en détail le fonctionnment de ce type d'animations.

Essentiellement, ces animations fonctionnent en utilisant animation-timeline et animation-range pour lier des animations css en keyframes aux éléments à animer.

Attention, ces propriétés ne peuvent pas être précisées dans le cadre de la propriété courte animation. Il faut placer ces déclarations après les propriétés courtes dans vos CSS, sous peine de les voir remises à une valeur de auto par la propriété courte qui les suivrait. L'utilisation de propriétés détaillée permet de ne pas devoir tenir compte de l'ordre des déclarations.

Scroll timelines

Permettent de lier une animation à un élément qui défile en utilisant la barre de scroll comme scrubber. La propriété animation-timeline a comme valeur une fonction scroll() qui prend deux paramètres:

  • l'élément dont le défilement est utilisé comme scroller (le défaut est le premier parent qui défile).
  • la direction dans laquelle le défilement doit être considéré.

Un use case typique est une barre de progression pour la lecture d'un article ou d'un blogpost.

.c-progressbar {
  position: sticky;
  top: 0;
  left: 0;
  height: 6px;
  background-color: #b0957c;
  z-index: 10;

  animation-timeline: scroll(root block);
  animation-name: progressGrow;
  animation-timing-function: linear;
  animation-fill-mode: both;
}

View timelines

Permettent de lier une animation à un élément qui défile en examinant la position de cet élément par rapport à son scroller. La propriété animation-timeline a comme valeur une fonction view() qui prend comme paramètre la direction de définlement à considérer

Par defaut, une view timeline commence lorsque le permier pixel de l'élément entre dans le scroller et se termine lorsque le dernier pixel le quitte. La propriété animation-range permet de modifier cette timeline par defaut.

Dans l'exemple ci-dessous, la timeline commence lorsque l'élément est à 33% dans le scroller et se termine lorsque l'élément est a 75% affiché dans le scroller.

.a-imgreveal {
  animation: imgReveal linear both;

  animation-timeline: view(block);
  animation-range: entry 33% entry 75%;
}

Timelines nommées

Dans certains cas, il est nécessaire de référencer un élément précis come scroller à l'aide de timelines nommées à l'aide des propriétés view-timeline-name, view-timeline-axis, scroll-timeline-name et scroll-timeline-axis.

.c-projects__item {
  view-timeline-name: --projectTimeline;
  view-timeline-axis: block;
}

.c-project {
  animation: projectsIn 0.2s ease-out both;
  animation-timeline: --projectTimeline;
  animation-range: entry 25% entry 50%;
}

Spécifier animation-range dans les keyframes

Il est également possible de spécifier le range d'une animation liée au scroll directement dans les keyframes de l'animation. Cela permet entre-autres de lier plusieurs animations (entrée et sortie par exemple) à un seul élément.

@keyframes animate-in-and-out {
  entry 0% {
    opacity: 0;
    transform: translateY(100%);
  }
  entry 100% {
    opacity: 1;
    transform: translateY(0);
  }
  exit 0% {
    opacity: 1;
    transform: translateY(0);
  }
  exit 100% {
    opacity: 0;
    transform: translateY(-100%);
  }
}

#list-view li {
  animation: linear animate-in-and-out;
  animation-timeline: view();
}

Animation déclenchées au scroll: IntersectionObserver

Avec l'aide Javascript, les transitions et animations CSS peuvent facilement être déclenchées au scroll.

IntersectionObserver est une API native qui permet facilement de détecter si un ou plusieurs éléments sont en intersection avec d'autres éléments ou avec le viewport du navigateur pour déclencher des animations via quelques changements de classes CSS. Voici une petite démonstration rapide.

Exercice: décortiquer le script et voir comment CSS et JS interagissent

Filtres

Les filtres peuvent servir à appliquer des effets simples sur des élements du DOM, typiquement des images. Les filtres fonctionnent à l'aide de la propriété filter pour laquelle on spécifie comme valeur un type de filtre et une valeur.

Vous pouvez vous référer à MDN pour une liste complète des filtres disponibles.

Il est également possible de réaliser des filtres plus complexes à l'aide de SVG et de les appliquer à votre contenu HTML. Voici un bon tutoriel sur le sujet par Sara Soueidan.

exemples

.u-grayscale {
  filter: grayscale(100%);
}

.u-blur {
  filter: blur(3px);
}

Blend modes

Les propriétés background-blend-mode et mix-blend-mode permettent de modifier vos images de façon importante, comme vous le feriez avec des calques dans une application graphique. background-blend-mode se charge faire un blend mode entre deux backgrounds, tandis que mix-blend-mode est utilisé pour gérer un blend mode entre un élément et un autre.

/* mix blend mode */
.o-blended-red {
  display: inline-block;
  background-color: red;
}

.o-blended-red > img {
  filter: grayscale(1);
  mix-blend-mode: multiply;
  vertical-align: middle;
}

Vous pouvez vous référer à MDN pour une liste complète des background-blend-mode et des mix-blend-mode disponibles.

Clips et masques

Clipping et masking peuvent également aider à apporter un peu de variété à vos images. Ces deux principes se ressemblent en ce qu'ils servent tous les deux à cacher certaines parties d'un élément. Le support au niveau des navigateurs n'est pas identique mais voici une page de test par Yoksel pour vérifier par vous mêmes.

  • masques: sont des images. Avec mask-mode: luminance; les parties noires du masque sont cachés, les parties blanches sont visibles. Avec mask-mode: alpha; les parties opaques du masque sont visibles et les parties transparentes cachées.
  • clips: sont des formes. Ce qui est à l'intérieur de la forme est visible

Voici un bon résumé des choses sur CSS-Tricks. Comme cela date un peu, je vous invite à également regarder la doc de MDN à ce sujet: mask et clip-path.

/* appliqué à une <img> */
.masked {
  -webkit-mask-image: url(../img/masks-scribbles.svg);
  mask-image: url(../img/masks-scribbles.svg);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
/* appliqué à une <img> (ne fontionne qu'avec un svg inclus dans le document pour Safari, Chrome et Opera) */

/* SVG externe / lié au document */
.clipped-svg {
  -webkit-clip-path: url(../img/clip.svg#myClip);
  clip-path: url(../img/clip.svg#myClip);
}

/* SVG interne au document */
.clipped-svg {
  -webkit-clip-path: url(#myClip);
  clip-path: url(#myClip);
}
<svg width="137" height="130" viewBox="0 0 137 130" xmlns="http://www.w3.org/2000/svg">
<title>Star</title>
<defs>
  <clipPath id="myClip">
    <path fill="#D8D8D8" d="M68.5 107.25l-42.027 22.095L34.5 82.547.5 49.405l46.987-6.827L68.5 0l21.013 42.578 46.988 6.827-34 33.142 8.026 46.798z" fill-rule="evenodd"/>
  </clipPath>
</defs>
</svg>
/* appliqué à une <img> */
.clipped-polygon {
  -webkit-clip-path: polygon(
    20% 0%,
    0% 20%,
    30% 50%,
    0% 80%,
    20% 100%,
    50% 70%,
    80% 100%,
    100% 80%,
    70% 50%,
    100% 20%,
    80% 0%,
    50% 30%
  );
  clip-path: polygon(
    20% 0%,
    0% 20%,
    30% 50%,
    0% 80%,
    20% 100%,
    50% 70%,
    80% 100%,
    100% 80%,
    70% 50%,
    100% 20%,
    80% 0%,
    50% 30%
  );
}

Clippy de Bennett Feely est un petit outil qui vous permettra de créer facilement des clip paths CSS.

/* appliqué à une <img> */
.c-gradient-text {
  background-image: linear-gradient(to right, #e03d52, #ffb25b);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

Les SVG et les polygones étant animables, ainsi que les images utilisées comme background, il est possible de réaliser des masques animés en CSS ou en JS.

Exercice: expérimenter avec clipping et masques dans Figma et en code

Animations JavaScript

Les animations en Javascript offrent bien plus de contrôle que les animations CSS si vous avez besoin d'interactivité, d'effets poussé ou de séquences d'animations chainées les unes aux autres.

Des librairies telles que GSAP de Greensock offrent une grande facilité d'utilisation et permettent de créer des animations complexes avec SVG, HTML ou Canvas. Ces librairies sont extérieures aux navigateurs mais offrent une grande palette de possibilités aux dévelopeurs. En voici un petit exemple avec un formulaire de login.

Au niveau des navigateurs justement, Web animation API est un standard qui se développe bien et dont les fonctions de bases bénéficient d'un bon support dans les navigateurs récents. Cette spécification est déjà intéressante à utiliser aujourd'hui et deviendra encore plus importante lorsque le support des navigateurs augmentera pour les fonctions avancées (séquences et timeline). Il est également possible d'utiliser requestAnimationFrame, qui est plus complexe à gérer au niveau performance mais vous permet de créer à peu près n'importe quelle animation.

L'animation est devenue une part importante des interfaces et du web en général, en partie parce que nous y sommes habitués sur les plateformes mobiles natives comme iOS ou Androïd.

Comme à son habitude, le web intègre cela et avance en direction d'une expérience utilisateur plus riches dans lesquelles l'animation devient de plus en plus importante.

Comme dit plus haut, la librairie Greensock / GSAP est le standard du moment et offre les avantages suivants:

  • facile d'utilisation
  • attention accordée à la performance (versions light et max)
  • fonctionnalités impressionnantes
  • bonnes ressources et tutoriaux
  • possibilité d'animer également les SVG
  • gestion des inconsistances dans les navigateurs.

Voici le HTML et le CSS utilisés pour quelques exemples très simples

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Animations GSAP</title>
    <link rel="stylesheet" href="css/main.css" />
  </head>
  <body>
    <div class="box  js-box"></div>

    <!-- lib -->
    <script src="https://cdn.jsdelivr.net/npm/gsap@3.0.1/dist/gsap.min.js"></script>

    <!-- script -->
    <script src="js/anims.js"></script>
  </body>
</html>
.box {
  width: 50px;
  height: 50px;
  background-color: red;
}

Au niveau du code JavaScript, commençons par des Tweens simples. GSAP vous permet de réaliser des Tweens de deux façons différentes:

  • to: utilise les caractéristiques de l'élément comme première frame du tween
  • from: utilise les caractéristiques de l'élément comme dernière frame du tween

Dans tous les exemples donnés ici, nous utiliserons des transformations CSS pour les déplacements, dans la mesure où elles n'ont pas d'impact sur les autres éléments de la page, utilisent la carte graphique plutôt que le processeur et causent un minimum de repaints de la part du navigateur.

Tweens avec GSAP

const myBox = document.querySelector(".js-box");

// To tween
// utilise les caractéristiques de départ
// spécifie les caractéristiques d'arrivée
gsap.to(myBox, {
  rotation: 180,
  x: 100,
  duration: 1,
  backgroundColor: "#0000FF",
});
const myBox = document.querySelector(".js-box");

// From tween
// utilise les caractéristiques d'arrivée
// spécifie les caractéristiques de départ
gsap.from(myBox, {
  rotation: 180,
  x: 100,
  duration: 1,
  backgroundColor: "#0000FF",
});
const myBox = document.querySelector(".js-box");

// toFrom tween
// spécifie les caractéristiques d'arrivée et de départ
gsap.fromTo(
  myBox,
  {
    rotation: 21,
    backgroundColor: "#00FF00",
  },
  {
    delay: 1,
    rotation: 180,
    x: 250,
    duration: 1,
    backgroundColor: "#0000FF",
  }
);
const myBox = document.querySelector(".js-box");

// Using set
// spécifie les caractéristiques d'arrivée et de départ
gsap.set(myBox, {
  rotation: 21,
  backgroundColor: "#00FF00",
});

gsap.to(myBox, {
  delay: 1,
  rotation: 180,
  x: 250,
  duration: 1,
  backgroundColor: "#0000FF",
});

Avec GSAP, nous pouvons donc modifier différentes propriétés CSS à la fois et animer quasiment toutes les propriétés CSS, même si il est conseillé de se limiter le plus possible a transfrom et opacity pour des raisons de performance. La notation est souvent la même que celle des propriétés CSS mais en camelCase.

Vous avez également à votre disposition une large bibliothèque de fonctions d'Easing et vous pouvez définir vos propres effets avec CustomBounce, CustomEase et CustomWiggle.

const myBox = document.querySelector(".js-box");

// To tween
gsap.to(myBox, {
  x: 100,
  ease: "elastic. out(1, 0.2)",
  duration: 0.5,
});

La gestion des délais est également facilitée.

// add delay
const myBox = document.querySelector(".js-box");

gsap.to(myBox, {
  x: 100,
  ease: "elastic. out(1, 0.2)",
  duration: 0.5,
  delay: 1,
});

Si vous avez plsusieurs éléments à animer, la fonction stagger est très pratique.

// stagger
const myBoxes = document.querySelectorAll(".js-box");

// using stagger
gsap.to(myBoxes, {
  stagger: 0.1,
  rotation: 180,
  x: 200,
});

Timeline avec GSAP

L'un des avantages centraux de GSAP est que cette librairie vous permet facilement de gérer des animations complexes grâce à un concept de timeline. Modifier les timings d'une animation complexe avec des éléments en successions et survenant en même temps devient un exercice relativement simple.

const myBox = document.querySelector(".js-box");

// simple timeline with parameters
let tl = gsap.timeline({ repeat: -1, yoyo: true });
tl.pause();

tl.to(myBox, {
  x: 200,
  duration: 0.5,
});

tl.to(myBox, {
  backgroundColor: "blue",
  rotation: 360,
  duration: 0.1,
  repeat: 5,
});

tl.to(myBox, {
  y: 200,
  duration: 1,
});

tl.to(myBox, {
  backgroundColor: "green",
  x: 0,
  duration: 0.2,
});

tl.to(
  myBox,
  {
    backgroundColor: "red",
    y: 0,
    duration: 0.25,
  },
  "-=0.2"
);

tl.play();

Les timelines peuvent aussi être utilisées de façon impriquées pour avoir un meilleur contrôle de vos animation et en nommer les différentes parties.

// Self invoking function
// Avoid variables collisions by scoping them
(function () {
  // nested timelines
  // better for composing complex animations and overlap
  const myBox = document.querySelector(".js-box");

  function one() {
    let tl = gsap.timeline();
    tl.to(myBox, { x: 200, duration: 1, delay: 1 });
    return tl;
  }

  function two() {
    let tl = gsap.timeline();
    tl.to(myBox, {
      backgroundColor: "blue",
      rotation: 360,
      duration: 0.5,
      repeat: 3,
    });
    return tl;
  }

  function three() {
    let tl = gsap.timeline();
    tl.to(myBox, {
      y: 200,
      duration: 1,
    });
    return tl;
  }

  function four() {
    let tl = gsap.timeline();
    tl.to(myBox, {
      backgroundColor: "green",
      x: 0,
      duration: 0.25,
    });
    return tl;
  }

  function five() {
    let tl = gsap.timeline();
    tl.to(myBox, {
      backgroundColor: "red",
      y: 0,
      duration: 1,
    });
    return tl;
  }

  let master = gsap.timeline();
  master.pause();
  master
    .add(one())
    .add(two(), "+=2")
    .add(three(), "-=1")
    .add(four())
    .add(five());
  master.play();
})();

Voici un exemple plus abouti utilisant des timelines imbriquées pour gérer efficacement les diverses parties d'une animation complexe.

Exercice: décortiquer ensemble le script et voir comment les choses fonctionnent

Ressources