Generative Design

Canvas 101

2526 · INMI · Dekens Antoine

Le setup

L'élément canvas permet de manipuler des pixels dans notre HTML.

Première chose à faire: définir notre canvas.

<canvas class='myCanvas'></canvas>
// Soit on récupère une balise canvas existante
const canvas = document.querySelector( ".myCanvas" );

// Soit on le crée
const body = document.querySelector( "body" );
const canvas = document.createElement( "canvas" );
body.append( canvas );

Les dimensions

Par défaut, un canvas a une largeur de 300px et une hauteur 150px. On utilise les propriétés width et height de notre canvas pour changer sa taille.

// On change la largeur et la hauteur.
// Inutile de préciser une unité,
// un canvas interprète les valeurs en pixels.
canvas.width = 500;
canvas.height = 500;

Récupérer la taille de l'écran

// Largeur totale de votre fenêtre
const screenWidth = window.innerWidth;

// Hauteur totale de votre fenêtre
const screenHeight = window.innerHeight;

Récupérer la taille d'un élément

<section class="wrapper"></section>
const wrapper = document.querySelector( '.wrapper' );

// Largeur totale de notre élément section.wrapper
const wrapperWidth = wrapper.clientWidth;

// Hauteur totale de notre élément section.wrapper
const wrapperHeight = wrapper.clientHeight;

Le contexte

Pour pouvoir dessiner quelque chose dans notre canvas, il nous faut une dernière chose: le contexte. Ce dernier est une boîte à outils, qui contiendra nos méthodes, il en existe 2:

  • 2d
  • webgl2 (3d)
const canvas = document.querySelector( ".myCanvas" );

// Charge nos méthodes dans une
// constante "ctx", qui pourra être utilisé
// pour dessiner en 2d.
const ctx = canvas.getContext( "2d" );

Fonction draw

On va se prévoir une fonction draw qui contiendra notre logique de dessin :

const draw = () => {
  // Notre logique ici
};

Formes &
densité

Rectangles

// Dessine un rectangle et ajoute une couleur de fond (noire par défaut)
ctx.fillRect( x, y, width, height );

// Dessine et ajoute un contour (noir par défaut)
ctx.strokeRect( x, y, width, height );
  • x: La position horizontale du coin supérieur gauche
  • y: La position verticale du coin supérieur gauche
  • width: La largeur du rectangle
  • height: La hauteur du rectangle

beginPath & closePath

beginPath et closePath permettre d'ouvrir et de fermer le dessin actuel. fillRect() et strokeRect() le fond automatiquement, mais pas la méthode rect() qui permet de les enchainer pour créer des tracés connectées :

fill & stroke

La méthode fill() permet d'appliquer une couleur de remplissage sur une ou plusieurs tracés connectés. Tandis que stroke() appliquera un contour.

// Ouvre un tracé, dessine et rempli la forme et ferme le tracé en une fois.
ctx.fillRect( x, y, width, height );

// La même opération avec rect()
ctx.beginPath();
  // Une indentation entre beginPath et closePath
  // permet de visualiser les forme dans le tracé actuel.
  ctx.rect( x, y, width, height );
ctx.closePath();
ctx.fill();

Densité de pixel

Device Pixel Ratio (ou DPR)

Si votre écran à une densité de pixel plus grande que 1 ( mac, smartphones, ect.), ce que nous avons dessiné est flou, surtout sur les contours.

Il faut voir le canvas comme une balise image: elle est composée de pixels. Et comme une image, si on veut qu'elle soit nette, il faut que sa résolution reflète le nombre de pixel dessiné, multiplié par la densité de pixel de votre écran.

Ex: Sur un écran de DPR 2, un canvas de 200px doit avoir une résolution de 400px pour être net.
// Retourne la densité de pixel de l'écran
const dpr = window.devicePixelRatio;

// Modifier la densité de pixel de notre canvas sur base de la densité
canvas.width = width * dpr;
canvas.height = height * drp;

// Agrandi l'échelle de valeur de notre contexte.
// Cela permet de garder les proportions malgré une densité différente
ctx.scale( dpr, dpr );

// Force une taille visuelle de notre canvas depuis le CSS
canvas.style.width = width / dpr;
canvas.style.height = height / dpr;

Exercices A

Exercices B

Cercles…

// Dessine un cercle
ctx.arc( x, y, radius, startAngle, endAngle, counterclockwise = false );
  • x: La position horizontale du centre
  • y: La position verticale du centre
  • radius: Le rayon du cercle
  • startAngle: L'angle de début (en radian)
  • endAngle: L'angle de fin (en radian)
  • counterclockwise: La direction de l'arc de cercle (false par défaut)

Degré vs Radian

//-- Un tour de cercle
// deg = 360 ou rad = 2 * Math.PI

//-- Un quart de cercle
// deg = 90 ou rad = 0.5 * Math.PI

// Fonction pour convertir des radians en degrés
const radToDeg = ( rad ) => {
  return rad * ( 180 / Math.PI );
}

// Fonction pour convertir des degrés en radians
const degToRad = ( deg ) => {
  return deg * ( Math.PI / 180 );
}

Fonction circle

Utiliser arc() peut vite devenir fatigant pour dessiner des cercles complets. On peut se faciliter la tâche en ajoutant une fonction circle qui prendre 3 paramètres et les passera dans notre méthode arc :

  1. x
  2. y
  3. radius
// Soit on crée une fonction
const circle = ( x, y, radius ) => {
  ctx.arc( x, y , radius, 0, 2 * Math.PI );
};

Template Canvas

v1

Exercices C

En partant du template et sur base de l'exemple suivant, réaliser les différentes étapes pour atteindre un résultat similaire :

  1. créer une particule ronde avec une position aléatoire.
  2. modifier le radius de manière aléatoire.
  3. utiliser un tableau de couleurs pour changer la couleur de la particule de manière aléatoire.
  4. utiliser une boucle for et créer au moins 100 particules.

1/9

1/1