Des pixels
L’élément <canvas>
est apparu avec le HTML5, celui-ci est une zone rectangulaire qui permet de lire et écrire chaque pixel à l’unité ou par groupe et de manipuler ces données.
Techniquement, cela vous permet de dessiner ou de refaire des effets « Photoshop » dans une page web. Si vous êtes habitué à Processing et son rendu pixel, vous êtes dans un registre similaire. D’ailleurs, la version JavaScript de Processing P5JS utilise la balise canvas.
L’inconvénient du canvas est sans doute le calcul des opérations, si vous voulez manipuler chaque pixel d’une image de 10 sur 10 pixels, cela donne 100 calculs, pour 100 pixels sur 100, 10 000, et pour du « full hd » de 1920 sur 1080 pixels, plus de 2 millions d’opérations.
Malgré ceci, on pourra utiliser cette balise à travers P5JS, des petits jeux à l’aide d’une librairie, des démos et autres.
HTML, SVG ou Canvas
Attention, refaire une interface en 100% canvas, n’est pas simple et amène son lot de problèmes en interactivité, accessibilité, référencement, responsive. On réservera cette balise pour les effets, les jeux et les expérimentations. Pour des animations simples, vous pouvez animer les éléments HTML via CSS ou SVG via JS.
Charger des images
Autres problèmes fréquents avec canvas le web ; vous ne pouvez pas analyser une image si celle-ci n’est pas chargée à 100%. Lancer une fonction d’analyse avant chargement retournera un résultat faux ou une erreur.
Un damier de 2 images
Cloner l’image dans le canvas
Pour le HTML, j’ai besoin d’un canvas et d’une image. Attention, j’ai fixé la taille du canvas dans le HTML !
<img id="imgA" src="https://picsum.photos/g/400/400/?random" alt=""><!-- image ~ lorem ipsum 400 sur 400 --> <canvas id="canvas" width="400" height="400"></canvas>
// voir https://developer.mozilla.org/fr/docs/Tutoriel_canvas/Utilisation_d'images // mon élément canvas var canvas = document.querySelector('#canvas'); // truc à faire pour écrire ou lire var ctx = canvas.getContext('2d'); // on crée une image temporaire var img_tmp = new Image(); // on ajoute un écouteur qui surveille le chargement de la src img_tmp.addEventListener('load',function() { // * // on clone et on place à 0,0 notre image ctx.drawImage(img_tmp, 0,0); }); // on donne une source à notre image_tmp (ce qui lancera le load de la ligne *) img_tmp.src = document.querySelector('#imgA').src;
La méthode drawImage permet de passer une image source et jusqu’à 8 paramètres de coordonnées, dimensions de la source vers sa destination (le canvas).
ctx.drawImage(image, dx, dy); // d => destination ctx.drawImage(image, dx, dy, dWidth, dHeight); ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); // s => source
On s’accroche !
ctx.drawImage(img_tmp, 100,100,200,200, // va prendre un carré de 200 sur 200 px à partir de 100,100 100,100,200,200); // le colle à 100,100 sur 200 sur 200
ctx.drawImage(img_tmp, 100,100,200,200, // va prendre un carré de 200 sur 200 px à partir de 100,100 100,100,100,100); // le colle à 100,100 sur 100 sur 100 (ce qui le redimensionne de 50%)
Des bandes
En maitrisant une boucle, je dessine des bandes de 10 sur 400 que je décale de 20 pixels.
for(var i=0;i<20;i++){ ctx.drawImage(img_tmp, i*20,0,10,400, i*20,0,10,400); }
Un damier
Plus complexe, cela demande deux boucles imbriquées et une astuce mathématique.
1re étape, avec une case de 10 pixels, j’ai besoin de 40 lignes (j40) et 20 colonnes (i20).
for(var j=0;j<40;j++){ for(var i=0;i<20;i++){ ctx.drawImage(img_tmp, i*20,j*10,10,10, i*20,j*10,10,10); } }
Hélas, j’obtiens des bandes car les lignes paires ne se décalent pas. Pour remédier à ceci, « %2 » est notre ami. Il s’agit du « modulo de 2 » qui retourne 1 si le chiffre est impaire ou 0 si le chiffre est paire.
0%2=0
1%2=1
2%2=0
3%2=1
Je vais donc ajouter 10 au x selon j%2 (si la ligne est impaire + 10, sinon + 0).
ctx.drawImage(img_tmp, i*20+j%2*10,j*10,10,10, i*20+j%2*10,j*10,10,10);
Et si je veux décaler le damier.
ctx.drawImage(img_tmp, i*20+(j+1)%2*10,j*10,10,10, i*20+(j+1)%2*10,j*10,10,10);
Avec deux images
See the Pen canvas 07 by Benoît Wimart (@benoitwimart) on CodePen.