Du CSS aux Shaders WebGL :
panorama des
techniques d'animation
en 2023

Julien Sulpis

Salut 👋 moi c'est

Julien Sulpis

J'aime faire des trucs cools sur le web

Ça va ĂȘtre dense !

(mais fun)

Avant de commencer... 

Avant de commencer...

Pourquoi faire des animations ? 

Avant de commencer...

Pourquoi faire des animations ?

  • ✔ Faciliter la comprĂ©hension
  • ✔ Apporter de la fluiditĂ©
  • ✔ Donner du feedback
  • ✔ Montrer son image de marque
  • ...

Avant de commencer...

Qu'est-ce qu'on peut animer ? 

Avant de commencer...

Qu'est-ce qu'on peut animer ?

ÉlĂ©ments du DOM (Document Object Model)

  • <div />
  • <button />
  • <input />
  • <img />
  •    ...

Avant de commencer...

Qu'est-ce qu'on peut animer ?

Canvas

<canvas />

Avant de commencer...

Du code au pixel 

Avant de commencer...

Du code au pixel

Avant de commencer...

Du code au pixel

JavaScript

Modification dynamique de la page

Avant de commencer...

Du code au pixel

Style

Quelles sont les propriétés CSS de chaque élément HTML ?

Avant de commencer...

Du code au pixel

Layout

Quelle est la position et la taille de chaque élément sur la page ?

Avant de commencer...

Du code au pixel

Paint

Dessine un rectancle violet Ă  la position {X,Y} sur un calque A

Avant de commencer...

Du code au pixel

Composite

Assemble et dessine les calques

Avant de commencer...

Du code au pixel

RecalculĂ© Ă  chaque frame 🔄

Avant de commencer...

Du code au pixel

CPU

Avant de commencer...

Du code au pixel

CPU

GPU

Avant de commencer...

Du code au pixel

CPU

Avant de commencer...

Du code au pixel

GPU

Avant de commencer...

Du code au pixel

Avant de commencer...

Du code au pixel

Avant de commencer...

Du code au pixel

đŸ„ł

Avant de commencer...

Du code au pixel

Bloque le main thread pendant 3 secondes

Shift + B : affiche le bouton en bas Ă  droite sur n'importe quelle slide
Ctrl + B (bouton visible) : bloque le main thread

Partie 1

Comment animer le DOM : les APIs natives

Transition CSS 

Transition CSS 

Usage: passage d’un Ă©tat A Ă  un Ă©tat B diffĂ©rents selon le plus court chemin

Transition CSS 

Usage: passage d’un Ă©tat A Ă  un Ă©tat B

Transition CSS

Utilisation

Transition CSS

Utilisation

css
.demo {
  transition: transform 800ms ease-in-out;

  &:checked {
    transform: translateX(80%);
  }
}
👍

Transition CSS

Utilisation

Transition CSS

Utilisation

👍

Transition CSS

Utilisation

👍

css
.icon:hover {
  transform: rotate(1turn);
  transition: transform 800ms;
}

Transition CSS

SinusoĂŻdes

👋

Transition CSS

SinusoĂŻdes

bezier curve bezier curve bezier curve bezier curve bezier curve bezier curve bezier curve

Images et technique : CSS Tricks - Advanced CSS Animation Using cubic-bezier()

Transition CSS

SinusoĂŻdes

👋

css
.icon:hover {
  transition-property: transform;
  transition-duration: 800ms;
  transition-timing-function: cubic-bezier(0.5, 700, 0.5, -700);

  transform: rotate(0.0004turn);
}

Transition CSS

SinusoĂŻdes

👋

đŸ€™

đŸ€Œ

Transition CSS

Non linéaire

Transition CSS

Non linéaire

Transition CSS

DĂ©mos

codepen logo@jsulpis : Hamburger menu animation

Transition CSS

DĂ©mos

css
button[aria-expanded="true"] {
    path:nth-child(1) {
      transform: rotate(45deg) scaleX(1.35);
    }

    path:nth-child(2) {
      opacity: 0;
    }

    path:nth-child(3) {
      transform: rotate(-45deg) scaleX(1.35);
    }

    svg {
      transform: rotate(-180deg);
    }
  }
}

Transition CSS

DĂ©mos

Avatar wallpaper

Avatar : La Voie de l’Eau

·  2022  Â·  3h12

Jake Sully et Neytiri sont devenus parents. L'intrigue se déroule une dizaine d'années aprÚs les événements racontés dans le long-métrage originel. Leur vie idyllique, proche de la nature, est menacée lorsque la « Resources Development Administration », dangereuse organisation non-gouvernementale, est de retour sur Pandora...

codepen logo@jsulpis : Movie card with hover effect

Transition CSS

DĂ©mos

css
.synopsis {
  ...
  transition-duration: calc(var(--transition-duration) / 2);
  transition-delay: calc(var(--transition-duration) / 8);
}

.movie-card:hover .synopsis {
  ...
  transition-duration: var(--transition-duration);
  transition-delay: calc(var(--transition-duration) / 3);
}

Transition CSS

DĂ©mos

codepen logo@jsulpis : 3D Cards Flip

Transition CSS - recap

Étapes calculĂ©es Performance Polyvalence DifficultĂ©
5/5 4/5 facile 😊
%%{
		init: {
			'theme': 'base',
			'themeVariables': {
				'primaryBorderColor': 'black',
				'secondaryBorderColor': 'black',
				'tertiaryBorderColor': 'gray',
				'fontSize': '18px'
			}
		}
	}%%

		flowchart
    subgraph native["APIs natives "]
        direction LR
        trans(Transition CSS)
    end
	

Animation CSS 

Animation CSS 

Usage: animation composĂ©e d’au moins deux Ă©tats, qui peut ĂȘtre dĂ©clenchĂ©e immĂ©diatement et qui peut ne jamais se terminer

Animation CSS

Utilisation

Animation CSS

Utilisation

css
@keyframes slide {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(100%);
  }
}

.card {
  animation: slide 2s ease-in-out infinite alternate;
}

Animation CSS

Utilisation

css
@keyframes slide {
  from {
    transform: translateX(-100%);
  }
  to {
    transform: translateX(100%);
  }
}

.card {
  animation: slide 2s ease-in-out infinite alternate;
}

Animation CSS

Fade in

Animation CSS

Fade in

css
@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(15%);
  }
}

.card {
  animation: fadeIn 800ms ease-out backwards;
  animation-delay: calc(500ms + var(--index) * 100ms);
}

Animation CSS

Fade in

đŸƒâ€â™‚ïžÂ Â Course ⛷  Ski 🚮  VĂ©lo

Animation CSS

Loaders

Nous cherchons le meilleur itinéraire...

Animation CSS

Loaders

Animation CSS

Animation SVG

codepen logo@Mandy : CSS-only SVG animation

Animation CSS

ContrÎler l'exécution

css
animation-play-state: running | paused;
animation-direction: normal | reverse | alternate | alternate-reverse;
animation-delay: ...s;

Animation CSS

ContrÎler l'exécution

animation-play-state: paused;

animation-delay: 0.00s;

Animation CSS

ContrÎler l'exécution

css
.card {
  animation-name: flipCard;
  animation-duration: var(--duration);
  animation-play-state: paused;
  animation-fill-mode: forwards;
  animation-delay: calc(-1 * var(--progress) * var(--duration));
}

Animation CSS

ContrÎler l'exécution

Tentez-vous votre chance ?

C'est gagné !

Animation CSS - recap

Étapes calculĂ©es Performance Polyvalence DifficultĂ©
5/5 3/5 facile 😊
%%{
		init: {
			'theme': 'base',
			'themeVariables': {
				'primaryBorderColor': 'black',
				'secondaryBorderColor': 'black',
				'tertiaryBorderColor': 'gray',
				'fontSize': '18px'
			}
		}
	}%%

		flowchart
    subgraph native["APIs natives "]
        direction LR
        trans(Transition CSS) --> anim(Animation CSS)
    end
	

Web Animation API 

Web Animation API 

Usage: similaire aux transitions et animations CSS, mais contrĂŽlables finement en javascript

Web Animation API

WAAPI: superset of CSS transitions and animations

Web Animation API

WAAPI support

Web Animation API

Utilisation

Web Animation API

Utilisation

css
@keyframes slide {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(100%);
  }
}

.card {
  animation-name: slide;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}

Web Animation API

Utilisation

css
@keyframes slide {
  0% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(100%);
  }
}

.card {
  animation-name: slide;
  animation-duration: 2s;
  animation-timing-function: ease-in-out;
  animation-iteration-count: infinite;
  animation-direction: alternate;
}
javascript
const card = document.querySelector('.card');

card.animate(
  [
    { transform: "translateX(-100%)" },
    { transform: "translateX(100%)" }
  ],
    {
      duration: 2000,
      easing: "ease-in-out",
      iterations: Infinity,
      direction: "alternate",
    }
);

Web Animation API

ContrÎler l'exécution

javascript
const animation = card.animate(keyframes, options);
				

Web Animation API

ContrÎler l'exécution

javascript
const animation = card.animate(keyframes, options);

animation.pause();

Web Animation API

ContrÎler l'exécution

javascript
const animation = card.animate(keyframes, options);

animation.pause();
...
animation.play();

Web Animation API

ContrÎler l'exécution

javascript
const animation = card.animate(keyframes, options);

animation.pause();
...
animation.play();
animation.cancel();
animation.reverse();

Web Animation API

ContrÎler l'exécution

javascript
const animation = card.animate(keyframes, options);

animation.pause();
...
animation.play();
animation.cancel();
animation.reverse();

const seek = (timestamp) => animation.currentTime = timestamp;

Web Animation API

ContrÎler l'exécution

codepen logo@jsulpis : 3D Card Flip - WAAPI

Web Animation API

ContrÎler l'exécution

Tentez-vous votre chance ?

C'est gagné !

Web Animation API - recap

Étapes calculĂ©es Performance Polyvalence DifficultĂ©
5/5 3/5 normal 😐
%%{
		init: {
			'theme': 'base',
			'themeVariables': {
				'primaryBorderColor': 'black',
				'secondaryBorderColor': 'black',
				'tertiaryBorderColor': 'gray',
				'fontSize': '18px'
			}
		}
	}%%

		flowchart
    subgraph native["APIs natives "]
        direction LR
        trans(Transition CSS) --> anim(Animation CSS)
        anim --> waapi(Web Animation API)
    end
	

requestAnimationFrame() 

requestAnimationFrame() 

Usage: toute action Ă  effectuer avant chaque frame rendue par le navigateur

requestAnimationFrame()

requestAnimationFrame()

Utilisation

javascript
window.requestAnimationFrame(() => {
  /* faire des trucs avant le rendu de la PROCHAINE frame */
});

requestAnimationFrame()

Utilisation

javascript
function animate(() => {
  /* faire des trucs avant le rendu de CHAQUE frame */
  requestAnimationFrame(animate);
})

animate();

requestAnimationFrame()

Utilisation

javascript
function loop(callback) {
  (function animate() {
    callback();
    requestAnimationFrame(animate);
  })();
}

loop(() => {
  // c'est plus clair !
})

requestAnimationFrame()

Exemples

javascript
loop(() => {
  performance.mark("next");
  const measure = performance.measure("duration", "current", "next");
  performance.mark("current");

  const frameDuration = measure.duration;
});

requestAnimationFrame()

Exemples

FPS

0.0ms par frame
codepen logo@jsulpis : FPS meter

requestAnimationFrame()

À retenir

Si tu peux le modifier en JavaScript, tu peux l'animer.

moi

requestAnimationFrame()

Exemples

javascript
loop(() => {
  // interpoler "progress"
  ...
  element.textContent = progress;
});
0

requestAnimationFrame()

Exemples

javascript
loop(() => {
  // interpoler "progress"
  ...
  element.setAttribute('value', progress);
});

requestAnimationFrame()

Animation Spring

requestAnimationFrame()

Animation Spring

requestAnimationFrame()

Animation Spring

requestAnimationFrame()

Animation Spring

requestAnimationFrame() - recap

Étapes calculĂ©es Performance Polyvalence DifficultĂ©
4/5 5/5 normal 😐
%%{
		init: {
			'theme': 'base',
			'themeVariables': {
				'primaryBorderColor': 'black',
				'secondaryBorderColor': 'black',
				'tertiaryBorderColor': 'gray',
				'fontSize': '18px'
			}
		}
	}%%

		flowchart
    subgraph native["APIs natives "]
        direction LR
        trans(Transition CSS) --> anim(Animation CSS)
        anim --> waapi(Web Animation API)
        waapi --> raf(requestAnimationFrame)
    end
	

Partie 2

Comment animer le DOM : les librairies JavaScript

JS meme

Une derniĂšre technique...

Une derniĂšre technique...

FLIP 

FLIP 

Usage: dĂ©placement d'Ă©lĂ©ments dans le DOM, ou autres animations qui ne peuvent ĂȘtre faites nativement.

FLIP

Explication

FLIP

Explication

FLIP

FLIP

Explication

FirstLastInvertPlay

FLIP

Explication

First

javascript
const element = document.querySelector(".my-element");

const first = element.getBoundingClientRect();

FLIP

Explication

Last

javascript
arrangeItems();

const last = element.getBoundingClientRect();

FLIP

Explication

Invert

javascript
const deltaX = first.left - last.left;
const deltaY = first.top - last.top;

element.style.transform = `translate(${deltaX}px, ${deltaY}px)`;

FLIP

Explication

Play

javascript
item.animate(
  [
    { transform: `translate(${deltaX}px, ${deltaY}px)` },
    { transform: "none" },
  ],
  { duration: 300, easing: "ease-in-out" }
);

FLIP

Explication

Frameworks JavaScript 

Frameworks JavaScript

Les APIs intégrées

Vue

Frameworks JavaScript

Les APIs intégrées

Vue


<Transition /> <TransitionGroup />

Frameworks JavaScript

Les APIs intégrées

Vue

<Transition />
HTML
<Transition>
  <p v-if="show">Bonjour</p>
</Transition>

Frameworks JavaScript

Les APIs intégrées

Vue

<Transition />
đŸƒâ€â™‚ïžÂ Â Course ⛷  Ski 🚮  VĂ©lo

Frameworks JavaScript

Les APIs intégrées

Vue

<Transition />
HTML
<Transition mode="out-in">
  <SkeletonLoading v-if="state === 'loading'" />
  <Content v-else />
</Transition>

Frameworks JavaScript

Les APIs intégrées

Vue

<Transition />
A

Frameworks JavaScript

Les APIs intégrées

Vue

<TransitionGroup />
HTML
<TransitionGroup name="list" tag="ul">
  <li v-for="item in items" :key="item">
    {{ item }}
  </li>
</TransitionGroup>

Frameworks JavaScript

Les APIs intégrées

Vue

<TransitionGroup />

Frameworks JavaScript

Les APIs intégrées

React

Frameworks JavaScript

Les APIs intégrées

React

gif desert

Frameworks JavaScript

Les APIs intégrées

Svelte

Frameworks JavaScript

Les APIs intégrées

Svelte


javascript
import { tweened, spring } from 'svelte/motion';

import { fade, fly, draw, crossfade, ... } from 'svelte/transition';

import { flip } from 'svelte/animate';

import { elasticIn, cubicOut, sineInOut, ... } from 'svelte/easing';

Frameworks JavaScript

Les APIs intégrées

Angular

Frameworks JavaScript

Les APIs intégrées

Angular

javascript
import { trigger, state, style } from '@angular/animations';

@Component({
  animations: [
    trigger('openClose', [
      state('open', style({
        opacity: 1,
        backgroundColor: 'yellow'
  })),
  ...
})
export class OpenCloseComponent { ... }

Frameworks JavaScript - recap

Étapes calculĂ©es Performance Polyvalence DifficultĂ©
5/5 3/5 normal 😐
%%{
		init: {
			'theme': 'base',
			'themeVariables': {
				'primaryBorderColor': 'black',
				'secondaryBorderColor': 'black',
				'tertiaryBorderColor': 'gray',
				'fontSize': '18px'
			}
		}
	}%%

		flowchart
    subgraph native["APIs natives "]
        direction LR
        trans(Transition CSS) --> anim(Animation CSS)
        anim --> waapi(Web Animation API)
        waapi --> raf(requestAnimationFrame)
    end

		subgraph frameworks["Frameworks JS"]
        direction TB
        subgraph Vue
            vueTransition[&ltTransition />, &ltTransitionGroup />]
        end
        subgraph Svelte
            transition[transition, motion, animate]
        end
        subgraph React
            shrug("¯\_ (ツ)_/¯")
        end
        subgraph Angular
            angularanimation("@angular/animations")
				end

    end

    native --> frameworks
		
	

Librairies JavaScript 

Librairies JavaScript

React

Framer Motion

La solution la plus complĂšte pour React

Librairies JavaScript

React

Framer Motion

JSX
export const MyComponent = ({ isVisible }) => (
  <AnimatePresence>
    {isVisible && (
      <motion.div
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
      />
    )}
  </AnimatePresence>
)

Librairies JavaScript

React

Framer Motion

Transitions FLIP Tween Spring Web Animation API requestAnimationFrame
✅ ✅ ✅ ✅ ✅ ✅

Taille (min + gzip) : 40.8kB

Librairies JavaScript

React

React Spring

Alternative Ă  Framer Motion

Librairies JavaScript

React

React Spring

JSX
function MyComponent() {
  const props = useSpring({
    from: { opacity: 0 },
    to: { opacity: 1 },
  })

  return <animated.div style={props}>Hello World</animated.div>
}

Librairies JavaScript

React

React Spring

Transitions FLIP Tween Spring Web Animation API requestAnimationFrame
✅ ✅ ❌ ✅ ❌ ✅

Taille (min + gzip) : 19.4kB

Librairies JavaScript

Vue

@vueuse/motion

La boĂźte Ă  outils pour Vue

Librairies JavaScript

Vue

@vueuse/motion

HTML
<template>
  <div
    v-motion
    :initial="{ opacity: 0 }"
    :visible="{ opacity: 1 }"
    :hovered="{ scale: 1.2 }"
    :leave="{ opacity: 0 }"
  />
</template>

Librairies JavaScript

Vue

@vueuse/motion

Transitions FLIP Tween Spring Web Animation API requestAnimationFrame
✅ ✅ ✅ ✅ ✅ ✅

Taille (min + gzip) : ~20kB

Librairies JavaScript

Vanilla JS

Vanilla JS

Librairies JavaScript

Vanilla JS

GSAP

La librairie de référence

(23.5kB)

Librairies JavaScript

Vanilla JS

GSAP

La librairie de référence

(23.5kB)

Alternative à gsap, légÚre et polyvalente

(7kB)

Librairies JavaScript

Vanilla JS

GSAP

La librairie de référence

(23.5kB)

Alternative à gsap, légÚre et polyvalente

(7kB)

Motion One

Web Animation API améliorée

(3.8kB)

Librairies JavaScript

Vanilla JS

npm trends for the 3 libraries

Librairies JavaScript

Vanilla JS

GSAP

Animation "simple"

javascript
gsap.to(".box", {
  rotation: 45,
  x: 100,
  duration: 1,
});

Librairies JavaScript

Vanilla JS

GSAP

Animation "simple"

codepen logo@GreenSock : 3D Animation with GSAP

Librairies JavaScript

Vanilla JS

Échelonnement ("stagger")

javascript
anime({
  targets: '.box',
  translateX: 200,
  delay: anime.stagger(100)
});

Librairies JavaScript

Vanilla JS

Échelonnement ("stagger")

animejs.com/documentation/#staggeringBasics

Librairies JavaScript

Vanilla JS

Échelonnement ("stagger")

animejs.com/documentation/#gridStaggering

Librairies JavaScript

Vanilla JS

Motion One

Scroll / Visibilité

javascript
scroll(
  animate(".progress-bar", { scaleX: [0, 1] })
);

Librairies JavaScript

Vanilla JS

Motion One

Scroll / Visibilité

0
motion.dev/dom/scroll#element-position

Librairies JavaScript

Vanilla JS

Motion One

SVG (path, morphing, drawing...)

codesandbox.io/s/6i8hve

Librairies JavaScript

Vanilla JS

Librarie Fonction "animate" Timeline Stagger Scroll Spring WAAPI SVG Poids
GSAP ✅✅✅✅ ❌❌✅23.5kB
Anime.js ✅✅✅✅ ✅❌✅7kB
Motion One ✅✅😐✅ ✅✅😐3.8kB

Librairies JavaScript

Vanilla JS

Retour sur les animations SVG...

Librairies JavaScript

Vanilla JS

GSAP

codepen logo@Josh : GreenSock SVG Bounce Animation

Librairies JavaScript

Vanilla JS

Librairies JavaScript

Vanilla JS

HTML
<dotlottie-player
  autoplay
  controls
  loop
  src="/animation.lottie"
  style="width: 300px"
/>

Taille (min + gzip) : 108.4kB


Librairies JavaScript

Vanilla JS


lottiefiles.com/39090-beautiful-city

Libraries JS - recap

Étapes calculĂ©es Performance Polyvalence DifficultĂ©
4/5 5/5 difficile 😬
%%{
		init: {
			'theme': 'base',
			'themeVariables': {
				'primaryBorderColor': 'black',
				'secondaryBorderColor': 'black',
				'tertiaryBorderColor': 'gray',
				'fontSize': '18px'
			}
		}
	}%%

		flowchart
    subgraph native["APIs natives "]
        direction LR
        trans(Transition CSS) --> anim(Animation CSS)
        anim --> waapi(Web Animation API)
        waapi --> raf(requestAnimationFrame)
    end

		subgraph frameworks["Frameworks JS"]
        direction TB
        subgraph Vue
            vueTransition[&ltTransition />, &ltTransitionGroup />]
        end
        subgraph Svelte
            transition[transition, motion, animate]
        end
        subgraph React
            shrug("¯\_ (ツ)_/¯")
        end
        subgraph Angular
            angularanimation("@angular/animations")
				end
    end

		subgraph libs1["Librairies Vanilla JS"]
        direction TB
        motionone(Motion One)
        animejs(Anime.js)
        gsap(GSAP)
        lottie(Lottie)
    end
    subgraph libs2["Librairies liées à un framework"]
        direction TB
        framer(Framer Motion)
        vuemotion("@vueuse/motion")
    end

    native --> frameworks
    native --> libs1
    frameworks --> libs1
    frameworks --> libs2
		
	

Ça va ?

gif respire

On respire, c'est pas fini...

Partie 3

Vers l'infini et au-delĂ  avec les animations de canvas

Canvas 2D 

Canvas 2D 

Usage: animation complexe et/ou interactive d'un grand nombre de formes géométriques lorsque les SVGs ne suffisent plus

Canvas 2D

Utilisation


HTML
<canvas width="400" height="400" />
javascript
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");

ctx.fillStyle = "hsl(200deg, 100%, 50%)";
ctx.fillRect(100, 100, 200, 200);

Canvas 2D

Utilisation

Canvas 2D

Utilisation

Canvas 2D

Utilisation

Si tu peux le modifier en JavaScript, tu peux l'animer.

encore moi

Canvas 2D

Utilisation

javascript
loop(() => {
  const time = Date.now();
  ...
  // monstre
  ctx.translate(Math.cos(time) * 30, 0);
  ...
  // bouche
  const angle = (Math.cos(time) + 1) / 3;
  ctx.arc(37, 37, 13, angle, -1 * angle, false);
  ...
})

Canvas 2D

Utilisation

Canvas 2D

Librairies

Fabric.js

Librairie généraliste pour le canvas 2D

Taille (min + gzip) : 85.5kB

Canvas 2D

Librairies

Matter.js

Moteur physique 2D

Taille (min + gzip) : 24.5kB

Canvas 2D

Librairies

Rive

Éditeur et runtime pour des animations interactives multiplateformes

Taille (min + gzip) : 20.9kB

Canvas 2D

Performance

Canvas 2D - recap

Étapes calculĂ©es Performance Polyvalence DifficultĂ©
4/5 2/5 difficile đŸ˜±
%%{
		init: {
			'theme': 'base',
			'themeVariables': {
				'primaryBorderColor': 'black',
				'secondaryBorderColor': 'black',
				'tertiaryBorderColor': 'gray',
				'fontSize': '18px'
			}
		}
	}%%

		flowchart
    subgraph native["APIs natives"]
        direction LR
        trans(Transition CSS) --> anim(Animation CSS)
        anim --> waapi(Web Animation API)
        waapi --> raf(requestAnimationFrame)
    end
    subgraph frameworks["Frameworks JS"]
        direction TB
        subgraph Vue
            vueTransition[&ltTransition />, &ltTransitionGroup />]
        end
        subgraph Svelte
            transition[transition, motion, animate]
        end
        subgraph React
            shrug("¯\_ (ツ)_/¯")
        end
        subgraph Angular
            angularanimation("@angular/animations")
				end

    end
    subgraph libs1["Librairies Vanilla JS"]
        direction TB
        motionone(Motion One)
        animejs(Anime.js)
        gsap(GSAP)
        lottie(Lottie)
    end
    subgraph libs2["Librairies liées à un framework"]
        direction TB
        framer(Framer Motion)
        vuemotion("@vueuse/motion")
    end
    subgraph canvas2D["Canvas 2D"]
        direction TB
        canvas2Dapi("Canvas 2D API")
        fabric(Fabric)
        rive(Rive)
    end
    native --> frameworks
    native --> libs1
    frameworks --> libs1
    frameworks --> libs2
    libs1 & libs2 --> a{" "}
    a --> canvas2D
	

Canvas WebGL 

Canvas WebGL 

Usage: mettre une claque Ă  vos utilisateurs Ă  coup d'animations qui sortent de l'ordinaire

Canvas WebGL

Utilisation


HTML
<canvas width="400" height="400" />
javascript
const canvas = document.querySelector("canvas");
const gl = canvas.getContext("webgl");







// Geometry
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(
	gl.ARRAY_BUFFER,
	new Float32Array([-1, -1, 1, -1, 0, 1]),
	gl.STATIC_DRAW
);

vertexBuffer.itemSize = 2;
vertexBuffer.numItems = 3;

// Shaders
const vertexShaderSource =
	"attribute vec2 a_position;" +
	"void main() { gl_Position = vec4 (a_position, 0,1); }";
const fragmentShaderSource =
	"precision mediump float;" +
	"void main() { gl_FragColor = vec4 (0.9,0,0.1,1); }";

const buildShader = function (shaderSource, typeOfShader) {
	const shader = gl.createShader(typeOfShader);
	gl.shaderSource(shader, shaderSource);
	gl.compileShader(shader);
	return shader;
};

const compiledVertexShader = buildShader(
	vertexShaderSource,
	gl.VERTEX_SHADER
);
const compiledFragmentShader = buildShader(
	fragmentShaderSource,
	gl.FRAGMENT_SHADER
);

// Setup GLSL program
const program = gl.createProgram();
gl.attachShader(program, compiledVertexShader);
gl.attachShader(program, compiledFragmentShader);
gl.linkProgram(program);
gl.useProgram(program);

// Draw
const positionLocation = gl.getAttribLocation(program, "a_position");
gl.enableVertexAttribArray(positionLocation);
gl.vertexAttribPointer(
	positionLocation,
	vertexBuffer.itemSize,
	gl.FLOAT,
	false,
	0,
	0
);
gl.drawArrays(gl.TRIANGLES, 0, vertexBuffer.numItems);

Canvas WebGL

Three.js

Three.js

Taille (min + gzip) : 154.28kB

Canvas WebGL

Three.js

javascript
// Scene
const scene = new THREE.Scene();

// Cube
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: "red" });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);

// Camera
const camera = new THREE.PerspectiveCamera(75, 1);
camera.position.z = 1;
scene.add(camera);

// Renderer
const renderer = new THREE.WebGLRenderer({ canvas });
renderer.setSize(400, 400);
renderer.render(scene, camera);
		

Canvas WebGL

Three.js

Si tu peux le modifier en JavaScript, tu peux l'animer.

encore re-moi

Canvas WebGL

Three.js

Animation par keyframes

javascript
gsap.to(
  camera.position,
  {
    x: 1
    duration: 2,
  }
);

Canvas WebGL

Three.js

Animation par keyframes

Canvas WebGL

Three.js

Animation par squelette

Canvas WebGL

Autres librairies

React-three-fiber

Renderer React pour three.js

Canvas WebGL

Autres librairies

React-three-fiber

Renderer React pour three.js

Trois.js

Librairie de composants three.js pour Vue

Canvas WebGL

Autres librairies

React-three-fiber

Renderer React pour three.js

Trois.js

Librairie de composants three.js pour Vue

Threlte

Librairie de composants three.js pour Svelte

Canvas WebGL

Autres librairies

Il n'y a pas que three.js ...

Canvas WebGL

Autres librairies

Shree.js

Version trÚs (trÚs) allégée de three.js (6.9kB)

Canvas WebGL

Autres librairies

Shree.js

Version trÚs (trÚs) allégée de three.js (6.9kB)

Pixi.js

Moteur de rendu WebGL 2D (219.6kB)

Canvas WebGL

Autres librairies

Shree.js

Version trÚs (trÚs) allégée de three.js (6.9kB)

Pixi.js

Moteur de rendu WebGL 2D (219.6kB)

Rive

Runtime pour des animations interactives, supporte Canvas 2D et WebGL (24.9kB)

Canvas WebGL

Pour aller plus loin...

Canvas WebGL

Pour aller plus loin...

(Il y a pas plus loin...)

Canvas WebGL

Shaders GLSL 

Canvas WebGL

Shaders GLSL

GPU

Canvas WebGL

Shaders GLSL

http://daureg.free.fr/ta_webit/fonctionnement.html

Canvas WebGL

Shaders GLSL

Vertex Shader

geométrie

codepen logo@jsulpis : Image deformation with WebGL shaders

Canvas WebGL

Shaders GLSL

Vertex Shader

geométrie

codepen logo@André Mattos : Loading...

Canvas WebGL

Shaders GLSL

http://daureg.free.fr/ta_webit/fonctionnement.html

Canvas WebGL

Shaders GLSL

Fragment Shader

couleur

Canvas WebGL

Shaders GLSL

Fragment Shader

couleur

Canvas WebGL

Shaders GLSL

Fragment Shader

couleur

Canvas WebGL - recap

Étapes calculĂ©es Performance Polyvalence DifficultĂ©
5/5 2/5 hardcore ☠
%%{
		init: {
			'theme': 'base',
			'themeVariables': {
				'primaryBorderColor': 'black',
				'secondaryBorderColor': 'black',
				'tertiaryBorderColor': 'gray',
				'fontSize': '18px'
			}
		}
	}%%

		flowchart
    subgraph native["APIs natives"]
        direction LR
        trans(Transition CSS) --> anim(Animation CSS)
        anim --> waapi(Web Animation API)
        waapi --> raf(requestAnimationFrame)
    end
    subgraph frameworks["Frameworks JS"]
        direction TB
        subgraph Vue
            vueTransition[&ltTransition />, &ltTransitionGroup />]
        end
        subgraph Svelte
            transition[transition, motion, animate]
        end
        subgraph React
            shrug("¯\_ (ツ)_/¯")
        end
        subgraph Angular
            angularanimation("@angular/animations")
				end

    end
    subgraph libs1["Librairies Vanilla JS"]
        direction TB
        motionone(Motion One)
        animejs(Anime.js)
        gsap(GSAP)
        lottie(Lottie)
    end
    subgraph libs2["Librairies liées à un framework"]
        direction TB
        framer(Framer Motion)
        vuemotion("@vueuse/motion")
    end
    subgraph canvas2D["Canvas 2D"]
        direction TB
        canvas2Dapi("Canvas 2D API")
        fabric(Fabric)
        rive(Rive)
    end
    subgraph webgl["Canvas WebGL"]
        direction TB
        three("three.js")
        shree(shree.js)
        pixi(pixi.js)

        subgraph shaders
            direction TB
            vertex
            fragment
        end

        three --> shaders
        shree --> shaders
        pixi --> shaders
    end
    native --> frameworks
    native --> libs1
    frameworks --> libs1
    frameworks --> libs2

    libs1 & libs2 --> a{" "}
    a --> canvas2D & webgl

		
	
%%{
		init: {
			'theme': 'base',
			'themeVariables': {
				'primaryBorderColor': 'black',
				'secondaryBorderColor': 'black',
				'tertiaryBorderColor': 'gray',
				'fontSize': '18px'
			}
		}
	}%%

		flowchart
    subgraph native["CSS / JS"]
    end
    subgraph frameworks["Framework JS"]
    end
    subgraph libs1["Librairie Vanilla JS"]
    end
    subgraph libs2["Librairie du framework"]
    end
    subgraph canvas2D["Canvas 2D"]
    end
    subgraph webgl["Canvas WebGL"]
    end

    native --> frameworks
    native --> libs1
    frameworks --> libs1
    frameworks --> libs2
    libs1 & libs2 --> a(" ")
    a --> canvas2D & webgl
	

Partie 4

Pour finir, et bien commencer

Pourquoi on fait ça déjà ? 

Pour finir

Pourquoi on fait ça déjà ?

homme excité

Tant d'animations possibles !

Pour finir

Pourquoi on fait ça déjà ?

Tu peux faire 1 animation sur une page, pas 15...

Tu peux faire 2 animations sur une page, pas 15...

Tu peux faire 3 animations Ă  la limite, mais pas 15...

...

Accessibilité 

Pour finir

Accessibilité

RĂ©duction du mouvement

css
@media (prefers-reduced-motion: no-preference) {
  /* mouvement important */
}

Pour finir

Accessibilité

RĂ©duction du mouvement

css
@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}
😕

Pour finir

Accessibilité

RĂ©duction du mouvement

css
@media (prefers-reduced-motion: no-preference) {
  .element {
    animation-name: myAwesomeAnimation;
    ...
  }
}
😀

Pour finir

Accessibilité

RĂ©duction du mouvement

javascript
if (window.matchMedia('(prefers-reduced-motion: no-preference)').matches) {
  animate();
}

Pour finir

Accessibilité

Accessibilité du contenu

HTML
<canvas
  height="400"
  width="650"
  role="img"
  aria-label="Texture de Bob l'Éponge qui ondule">
</canvas>

Inspiration 

Pour finir

Inspiration

Design

Code + Design

@jsulpis

github codepen twitter

@jsulpis

github codepen twitter
Technique Étapes calculĂ©es Performance Polyvalence DifficultĂ©
Transition CSS 5/5 4/5 facile 😊
Animation CSS 5/5 3/5 facile 😊
Web Animation API 5/5 3/5 normal 😐
requestAnimationFrame() 4/5 5/5 normal 😐
Frameworks JS 5/5 3/5 normal 😐
Librairies JS 4/5 5/5 difficile 😬
Canvas 2D 4/5 2/5 difficile đŸ˜±
Canvas WebGL 5/5 2/5 hardcore ☠