Utilisation d'images
Jusqu'à présent, nous avons créé nos propres formes et styles appliqués. L'une des fonctionnalités les plus intéressantes de <canvas>
est la possibilité d'utiliser des images. Celles-ci peuvent être utilisées pour faire de la composition dynamique de photos ou comme décors de graphes, pour des sprites dans des jeux, et ainsi de suite. Les images externes peuvent être utilisées dans n'importe quel format pris en charge par le navigateur, comme PNG, GIF ou JPEG. Vous pouvez même utiliser l'image produite par d'autres éléments du canevas sur la même page comme source !
L'importation d'images dans un canevas se déroule en deux étapes :
- L'obtention d'une référence à un objet
HTMLImageElement
ou à un autre élément canvas en tant que source. Il est également possible d'utiliser des images en fournissant une URL. - Le dessin de l'image à l'aide de la fonction
drawImage()
.
Voyons comment faire.
Obtenir des images à dessiner
L'API Canvas peut utiliser l'un des types de données suivants comme source d'image :
HTMLImageElement
-
Il s'agit d'images créées à l'aide du constructeur
Image()
, ainsi que de tout élément HTML<img>
. SVGImageElement
-
Ce sont des images incorporées en utilisant l'élément SVG
<image>
. HTMLVideoElement
-
L'utilisation d'un élément HTML
<video>
comme source d'image capture l'image actuelle de la vidéo et l'utilise comme une image. HTMLCanvasElement
-
Vous pouvez utiliser un autre élément
<canvas>
comme source d'image.
Ces sources sont collectivement référencées par le type CanvasImageSource
.
Il existe plusieurs façons d'obtenir des images pour une utilisation sur un canevas.
Utilisation d'images présentes sur la même page
Nous pouvons obtenir une référence aux images sur la même page que le canevas en utilisant l'un des éléments suivants :
- La collection
document.images
; - La méthode
document.getElementsByTagName()
; - Si vous connaissez l'identifiant de l'image spécifique que vous souhaitez utiliser, vous pouvez utiliser
document.getElementById()
pour retrouver cette image.
Utilisation d'images d'un autre domaine
En utilisant l'attribut crossorigin
d'un élément <img>
(reflété par la propriété HTMLImageElement.crossOrigin
), vous pouvez demander la permission de charger une image d'un autre domaine pour l'utiliser dans votre appel à drawImage()
. Si le domaine d'hébergement permet un accès interdomaine à l'image, l'image peut être utilisée dans votre canevas sans l'altérer; sinon utiliser l'image va corrompre le canevas.
Utilisation d'autres éléments canvas
Comme pour les images normales, nous accédons aux autres éléments <canvas>
en utilisant la méthode document.getElementsByTagName()
ou document.getElementById()
. Assurez-vous d'avoir dessiné quelque chose sur le canevas source avant de l'utiliser dans votre canevas cible.
Une des utilisations les plus pratiques de cette fonctionnalité serait d'utiliser un second élément canvas comme aperçu de taille réduite d'un canevas de grande taille.
Création d'une image à partir de rien
Une autre option est de créer de nouveaux objets HTMLImageElement
dans le script même. Pour ce faire, vous pouvez utiliser le constructeur Image()
.
let img = new Image(); // Crée un nouvel élément Image
img.src = "myImage.png"; // Définit le chemin vers sa source
Lorsque ce script est exécuté, l'image commence à être chargée.
Si vous essayez d'appeler drawImage()
avant le chargement de l'image, il ne fera rien (ou, dans les anciens navigateurs, cela pourra même déclencher une exception). Utilisez donc l'événement load
pour ne pas dessiner avant que l'image ne soit chargée :
let img = new Image(); // Crée un nouvel élément img
img.addEventListener(
"load",
function () {
// exécute les instructions drawImage ici
},
false,
);
img.src = "myImage.png"; // définit le chemin de la source
Si vous n'utilisez qu'une image externe, cela peut être une bonne approche, mais une fois que vous avez besoin de gérer plus d'une image, vous devrez recourir à quelque chose de plus astucieux. Nous ne verrons pas les stratégies de préchargement dans ce tutoriel, toutefois, gardez à l'esprit l'éventuelle nécessité de ces techniques.
Intégration d'une image via une URL de données
Un autre moyen possible d'inclure des images consiste à utiliser les URL de données (data: url
). Les URL de données vous permettent de définir complètement une image en tant que chaîne de caractères codée en Base64 directement dans votre code.
let img = new Image(); // Crée un nouvel élément img
img.src =
"data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==";
L'un des avantages des URL de données est que l'image résultante est disponible immédiatement, sans autre aller-retour au serveur. Cela permet également d'encapsuler dans un fichier tous vos CSS, JavaScript, HTML et images, ce qui les rend plus portables vers d'autres endroits.
Certains inconvénients de cette méthode sont que votre image n'est pas mise en cache, et que, pour les grandes images, l'URL encodée peut devenir assez longue.
Utilisation des images d'une vidéo
Vous pouvez également utiliser les images d'une vidéo présentée par un élément <video>
(même si la vidéo n'est pas visible). Par exemple, si vous avez un élément <video>
avec l'identifiant myvideo
, vous pouvez faire :
function getMyVideo() {
let canvas = document.getElementById("canvas");
if (canvas.getContext) {
let ctx = canvas.getContext("2d");
return document.getElementById("myvideo");
}
}
Cela renvoie l'objet HTMLVideoElement
pour la vidéo, qui, comme décrit précédemment, est l'un des objets pouvant être utilisé comme CanvasImageSource
.
Dessin d'images
Une fois la référence à l'objet image source obtenue, on peut utiliser la méthode drawImage()
pour l'afficher sur le canevas. Comme nous le verrons plus tard, la méthode drawImage()
est surchargée et possède trois variantes différentes. Dans sa forme la plus basique, elle ressemble à ceci :
drawImage(image, x, y)
-
Dessine le
CanvasImageSource
spécifié par le paramètreimage
aux coordonnées (x
,y
).
Note :
Les images SVG doivent spécifier une largeur et une hauteur dans l'élément racine <svg>
.
Exemple : un graphique linéaire simple
Dans l'exemple suivant, nous utiliserons une image externe comme fond pour un petit graphique linéaire. L'utilisation d'images de fond peut rendre vos scripts considérablement plus légers puisqu'il n'est alors pas nécessaire de dessiner des arrières-plans élaborés. Une seule image est utilisée ici, on utilise donc le gestionnaire d'évènement load
de l'objet image pour lancer les instructions de dessin. La méthode drawImage()
place l'image de fond aux coordonnées (0,0), soit le coin supérieur gauche du canevas.
function draw() {
console.log("tt");
let ctx = document.getElementById("canvas").getContext("2d");
let img = new Image();
img.onload = function () {
ctx.drawImage(img, 0, 0);
ctx.beginPath();
ctx.moveTo(30, 96);
ctx.lineTo(70, 66);
ctx.lineTo(103, 76);
ctx.lineTo(170, 15);
ctx.stroke();
};
img.src = "backdrop.png";
}
Le graphique résultant ressemble à ceci :
Mise à l'échelle
La seconde variante de la méthode drawImage()
ajoute deux paramètres supplémentaires et permet de placer des images redimensionnées sur le canevas.
drawImage(image, x, y, width, height)
-
Cette variante ajoute les paramètres
width
etheight
qui indiquent la taille à laquelle mettre à l'échelle l'image lorsqu'elle est dessinée sur le canevas.
Exemple : mosaïque à partir d'une image
Dans cet exemple, nous utiliserons une image comme fond d'écran en la répétant plusieurs fois sur le canevas. Cette opération est réalisée simplement en faisant une boucle qui place l'image redimensionnée à différentes positions. Dans le code ci-dessous, la première boucle for
s'occupe des lignes alors que la seconde gère les colonnes. L'image est redimensionnée à un tiers de sa taille originale, ce qui fait 50×38 pixels.
Note : Les images peuvent devenir floues lorsqu'elles sont agrandies ou granuleuses si elles sont réduites. Il vaut mieux ne pas redimensionner une image contenant du texte devant rester lisible.
function draw() {
let ctx = document.getElementById("canvas").getContext("2d");
let img = new Image();
img.onload = function () {
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 3; j++) {
ctx.drawImage(img, j * 50, i * 38, 50, 38);
}
}
};
img.src = "rhino.jpg";
}
Le canevas résultant ressemble à ceci :