Tutoriel canvas:Ajout de styles et de couleurs
Un article de MDC.
Sommaire |
Dans le chapitre à propos du dessin de formes géométriques, nous avons uniquement utilisé les styles de ligne et de remplissage par défaut. Dans ce chapitre, nous explorerons toutes les options de canvas que nous avons à notre disposition pour rendre nos dessins un peu plus attractifs.
[modifier] Couleurs
Jusqu'à présent, nous avons seulement vu des méthodes du contexte de dessin. Si nous voulons appliquer des couleurs à une forme, il y a deux propriétés importantes qui peuvent être utilisées : fillStyle et strokeStyle.
fillStyle = couleur
strokeStyle = couleur
strokeStyle est utilisée pour définir la couleur du contour de la forme et fillStyle est pour la couleur de remplissage. couleur peut être une chaîne représentant une valeur de couleur CSS, un objet gradient ou un objet pattern. Nous aborderons les objets gradient et pattern plus tard. Par défaut, les couleurs de contour et de remplissages sont définies en noir (valeur de couleur CSS #000000).
Les chaînes valides pouvant être entrées, selon la spécification, sont les valeurs de couleurs CSS3. Chacun des exemples suivant décrit la même couleur.
// chacune de ces instructions définit fillStyle à 'orange' ctx.fillStyle = "orange"; ctx.fillStyle = "#FFA500"; ctx.fillStyle = "rgb(255,165,0)"; ctx.fillStyle = "rgba(255,165,0,1)";
Note : Pour l'instant, toutes les valeurs de couleur CSS 3 ne sont pas gérées dans le moteur Gecko. Par exemple; les valeurs de couleur hsl(100%, 25%, 0) ou rgb(0,100%,0) ne sont pas permises. Si vous vous limitez à celles présentées ci-dessus vous ne rencontrerez aucun problème.
Note : Si vous définissez la propriété strokeStyle et/ou fillStyle, la nouvelle valeur devient celle par défaut pour toutes les formes dessinées à partir de cet instant. Pour chaque forme qui doit être dans une couleur différente, vous devrez réassigner les propriétés fillStyle ou strokeStyle.
[modifier] Un exemple d'utilisation de fillStyle
Dans cet exemple, on utilise à nouveau deux boucles for pour dessiner un quadrillage de rectangles, chacun dans une couleur différente. L'image résultante devrait ressembler à celle présentée ici à droite. Rien de très spectaculaire ne se passe. On utilise les deux variables i et j pour générer une couleur RGB (rouge, vert, bleu) pour chaque carré. Seules les valeurs rouges et vertes sont modifiées, le canal bleu a une valeur fixe. En modifiant les canaux, vous pouvez générer toutes sortes de palettes. En augmentant le nombre d'itérations, vous pouvez obtenir quelque chose qui ressemble aux palettes de couleur utilisées par Photoshop.
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
for (i = 0; i < 6; i++) {
for (j = 0; j < 6; j++){
ctx.fillStyle = 'rgb(' + Math.floor(255-42.5*i) + ',' +
Math.floor(255-42.5*j) + ',0)';
ctx.fillRect(j*25, i*25, 25, 25);
}
}
}
[modifier] Un exemple d'utilisation de strokeStyle
Cet exemple est similaire à celui présenté plus haut, mais en utilisant maintenant la propriété strokeStyle. On utilise également la méthode arc pour dessiner des cercles au lieu de carrés.
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
for (i = 0; i < 6; i++) {
for (j = 0; j < 6; j++) {
ctx.strokeStyle = 'rgb(0,' + Math.floor(255-42.5*i) + ',' +
Math.floor(255-42.5*j) + ')';
ctx.beginPath();
ctx.arc(12.5+j*25, 12.5+i*25, 10, 0, Math.PI*2, true);
ctx.stroke();
}
}
}
[modifier] Transparence
En plus de dessiner des formes opaques sur le canevas, on peut également dessiner des formes semi-transparentes. Ceci s'effectue en changeant la propriété globalAlpha, ou l'on pourrait aussi assigner une couleur semi-transparente au style de contour et/ou de remplissage.
globalAlpha = valeur de transparence
Cette propriété applique une valeur de transparence à toutes les formes dessinées sur le canevas. L'intervalle des valeurs acceptables va de 0.0 (totalement transparent) à 1.0 (totalement opaque). Par défaut, cette propriété est définie à 1.0 (totalement opaque).
La propriété globalAlpha peut être utile si on veut dessiner de nombreuses formes sur le canevas avec la même transparence. Cependant, l'option suivante est sans doute un petit peu plus pratique.
Étant donné que les propriétés strokeStyle et fillStyle acceptent les valeurs de couleur CSS 3, on peut utiliser la notation suivante pour leur assigner une couleur transparente.
// Assignation de couleurs transparentes aux styles de contour et de remplissage ctx.strokeStyle = "rgba(255,0,0,0.5)"; ctx.fillStyle = "rgba(255,0,0,0.5)";
La fonction rgba() est similaire à la fonction rgb(), mais possède un paramètre supplémentaire. Ce dernier paramètre définit la valeur de transparence de cette couleur particulière. Les valeur acceptées se trouvent à nouveau dans l'intervalle entre 0.0 (totalement transparent) et 1.0 (totalement opaque).
[modifier] Un exemple d'utilisation de globalAlpha
Dans cet exemple, on a dessiné un fond de quatre carrés de couleurs différentes. Par dessus, on ajoute une série de cercles semi-transparents. La propriété globalAlpha est positionnée à 0.2 et sera utilisée pour toutes les formes à partir de ce point. Chaque itération dans la boucle for dessine une série de cercles avec un rayon de taille croissante. En ajoutant de plus en plus de cercles les uns au dessus des autres, on réduit la transparence effective des cercles qui ont déjà été dessinés. Si l'on augmentait le compteur d'itérations pour dessiner encore plus de cercles, le fond disparaîtrait totalement du centre de l'image.
- Cet exemple ne fonctionnait pas dans Firefox 1.5 beta 1. Vous aurez besoin de la version finale ou d'une version plus récente pour voir celui-ci en action.
- Cet exemple ne fonctionne pas sous Safari parce que la couleur n'est pas spécifiée correctement. La couleur dans cet exemple est définie à '#09F', ce qui est invalide selon la spécification. Firefox accepte cependant la défnition de couleur mal formée.
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
// Dessin du fond
ctx.fillStyle = '#FD0';
ctx.fillRect(0, 0, 75, 75);
ctx.fillStyle = '#6C0';
ctx.fillRect(75, 0, 75, 75);
ctx.fillStyle = '#09F';
ctx.fillRect(0, 75, 75, 75);
ctx.fillStyle = '#F30';
ctx.fillRect(75, 75, 150, 150);
ctx.fillStyle = '#FFF';
// Définition de la valeur de transparence
ctx.globalAlpha = 0.2;
// Dessin de cercles semi transparents
for (i = 0; i < 7; i++) {
ctx.beginPath();
ctx.arc(75, 75, 10+10*i, 0, Math.PI*2, true);
ctx.fill();
}
}
[modifier] Un exemple utilisant rgba()
Dans ce second exemple, on fait quelque chose de similaire à ce que nous avons fait ci-dessus, mais au lieu de dessiner des cercles l'un sur l'autres, on dessine de petits rectangles avec une opacité croissante. L'utilisation de rgba() donne un peu plus de contrôle et de flexibilité puisqu'on peut définir les styles de contour et de remplissage séparément.
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
// Dessin du fond
ctx.fillStyle = 'rgb(255,221,0)';
ctx.fillRect(0, 0, 150, 37.5);
ctx.fillStyle = 'rgb(102,204,0)';
ctx.fillRect(0, 37.5, 150, 37.5);
ctx.fillStyle = 'rgb(0,153,255)';
ctx.fillRect(0, 75, 150, 37.5);
ctx.fillStyle = 'rgb(255,51,0)';
ctx.fillRect(0, 112.5, 150, 37.5);
// Affichage de rectangles semi transparents
for (i=0;i<10;i++){
ctx.fillStyle = 'rgba(255,255,255,'+(i+1)/10+')';
for (j=0;j<4;j++){
ctx.fillRect(5+i*14,5+j*37.5,14,27.5)
}
}
}
[modifier] Styles de ligne
Plusieurs propriétés permettent de changer le style des lignes.
lineWidth = valeur
lineCap = type
lineJoin = type
miterLimit = valeur
On pourrait les décrire en détail, mais c'est probablement plus facile à comprendre en regardant simplement les exemples ci-dessous.
[modifier] Un exemple d'utilisation de lineWidth
Cette propriété définit l'épaisseur de la ligne courante. Les valeurs doivent être des nombres positifs. Par défaut, elle est définie à 1.0.
Dans l'exemple ci-dessous, on a dessiné 10 lignes droites de plus en plus épaisses. Dans la configuration par défaut, une unité vaut 1 pixel. La ligne tout à fait à gauche est donc épaisse d'1 pixel et celle tout à fait à droite de 10 pixels.
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
for (i = 0; i < 10; i++) {
ctx.lineWidth = 1+i;
ctx.beginPath();
ctx.moveTo(5+i*14, 5);
ctx.lineTo(5+i*14, 140);
ctx.stroke();
}
}
[modifier] Un exemple d'utilisation de lineCap
La propriété lineCap détermine comment sont dessinés les points terminaux de chaque ligne. Les trois valeurs possibles pour cette propriété sont : butt, round et square. Par défaut, celle-ci est définie à butt.
Dans cet exemple, on a dessiné trois lignes, chacune avec une valeur différente pour la propriété lineCap. Deux guides ont également été ajoutés pour voir la différence exacte entre les trois. Chacune de ces lignes commence et se termine exactement sur ces guides.
La ligne de gauche utilise l'option par défaut butt. Vous remarquerez qu'elle est dessinée exactement à niveau des guides.
La seconde utilise l'option round. Celle-ci ajoute un demi-cercle au bout, avec pour rayon la moitié de l'épaisseur de la ligne.
La ligne de droite utilise l'option square. Celle-ci ajoute une boîte de la largeur de la ligne et haute de la moitié de son épaisseur.
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
var lineCap = ['butt', 'round', 'square'];
// Dessin des guides
ctx.strokeStyle = '#09f';
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(140, 10);
ctx.moveTo(10, 140);
ctx.lineTo(140, 140);
ctx.stroke();
// Dessin des lignes
ctx.strokeStyle = 'black';
for (i = 0; i < lineCap.length; i++) {
ctx.lineWidth = 15;
ctx.lineCap = lineCap[i];
ctx.beginPath();
ctx.moveTo(25+i*50, 10);
ctx.lineTo(25+i*50, 140);
ctx.stroke();
}
}
[modifier] Un exemple d'utilisation de lineJoin
La propriété lineJoin détermine comment deux lignes qui se rejoignent dans une forme sont attachées entre-elles. Il y a trois valeurs possibles pour cette propriété : round, bevel et miter. Par défaut, cette propriété est définie à miter.
À nouveau, nous avons dessiné trois chemins différents, chacun utilisant un des paramètres de la propriété lineJoin. Celui du dessus utilise l'option round. Cela arrondit les coins d'une forme. Le rayon de ces coins arrondis est égal à l'épaisseur de la ligne. La seconde ligne utilise l'option bevel et la troisième l'option miter. Dans ce dernier cas, les lignes sont rejointes en prolongeant les coins extérieurs pour se rejoindre en un seul point. Ce paramètre est affecté par la propriété miterLimit qui sera expliqué plus bas.
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
var lineJoin = ['round', 'bevel', 'miter'];
ctx.lineWidth = 10;
for (i = 0; i < lineJoin.length; i++){
ctx.lineJoin = lineJoin[i];
ctx.beginPath();
ctx.moveTo(-5, 5+i*40);
ctx.lineTo(35, 45+i*40);
ctx.lineTo(75, 5+i*40);
ctx.lineTo(115, 45+i*40);
ctx.lineTo(155, 5+i*40);
ctx.stroke();
}
}
[modifier] Une démonstration de la propriété miterLimit
Comme vous avez pu le voir dans l'exemple précédent, lorsque deux lignes sont rejointes en utilisant l'option miter, les coins extérieurs des deux lignes sont prolongés pour se rencontrer en un point. Pour les lignes formant un grand angle entre-elles, ce point n'est pas loin du point de connexion intérieur. Cependant, lorsque cet angle diminue, la distance (miter length) entre ces points augmente de façon exponentielle.
La propriété miterLimit détermine jusqu'à quelle distance le point de connexion extérieur peut être placé depuis le point de connexion intérieur. Si deux lignes dépassent cette valeur, une jointure en biseau sera dessinée.
Nous avons réalisé une petite démonstration dans laquelle vous pouvez changer miterLimit dynamiquement et en voir l'effet sur les formes sur le canevas. Les lignes bleues montrent les points de départ et d'arrivée de chacune des lignes sur le modèle en zigzag.
[modifier] Dégradés
Comme dans tout programme de dessin normal, il est possible de remplir des formes avec des dégradés de couleur linéaires et radiaux. On crée pour cela un objet canvasGradient à l'aide d'une des méthodes suivantes. Cet objet est ensuite assigné aux propriétés fillStyle ou strokeStyle.
createLinearGradient(x1, y1, x2, y2)
createRadialGradient(x1, y1, r1, x2, y2, r2)
La méthode createLinearGradient prend quatre arguments représentant le point de départ (x1, y1) et le point d'arrivée (x2, y2) du dégradé.
La méthode createRadialGradient prend six arguments. Les trois premiers définissent un cercle centré sur les coordonnées (x1, y1) et de rayon r1 et les suivants un cercle centré sur les coordonnées (x2, y2) et de rayon r2.
var lineargradient = new ctx.createLinearGradient(0, 0, 150, 150); var radialgradient = new ctx.createRadialGradient(75, 75, 0, 75, 75, 100);
Une fois qu'un objet canvasGradient a été créé, on peut lui assigner des couleurs en utilisant la méthode addColorStop.
addColorStop(position, color)
Cette méthode prend deux arguments. La position doit être un nombre entre 0.0 et 1.0 et définit la position relative de la couleur dans le dégradé. En la positionnant en 0.5 par exemple, on place la couleur précisément au mulieu du dégradé. L'argument color doit être une chaîne représentant une couleur CSS (par exemple #FFF, rgba(0,0,0,1), etc.)
Vous pouvez ajouter autant de points de couleur à un dégradé que vous voulez. Ci-dessous, un dégradé très simple du blanc vers le noir.
var lineargradient = new ctx.createLinearGradient(0, 0, 150, 150); lineargradient.addColorStop(0, 'white'); lineargradient.addColorStop(1, 'black');
[modifier] Un exemple d'utilisation de createLinearGradient
Dans cet exemple, on crée deux dégradés différents. Comme vous pouvez le voir, deux couleurs ont été assignées à la même position. Ceci est fait pour réaliser des transitions de couleur très brusques - dans ce cas du blanc vers le vert. Normalement, l'ordre dans lequel les points de couleur sont définis n'a pas d'importance, mais dans ce cas spécial elle est significative. Si vous laissez les assignations dans l'ordre dans lequel vous voulez les voir apparaître, il ne devrait pas y avoir de problème.
Dans le second dégradé, aucune couleur de départ n'a été assignée (à la position 0.0) étant donné que ce n'était pas strictement nécessaire. L'assignation de la couleur noire à la position 0.5 rend automatiquement le dégradé, depuis le départ jusqu'à ce point, tout à fait noir.
Comme vous pouvez le voir ici, tant la propriété strokeStyle que la propriété fillStyle peuvent recevoir un objet canvasGradient comme entrée valide.
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
// Création des dégradés
var lingrad = ctx.createLinearGradient(0, 0, 0, 150);
lingrad.addColorStop(0, '#00ABEB');
lingrad.addColorStop(0.5, '#fff');
lingrad.addColorStop(0.5, '#26C000');
lingrad.addColorStop(1, '#fff');
var lingrad2 = ctx.createLinearGradient(0, 50, 0, 95);
lingrad2.addColorStop(0.5, '#000');
lingrad2.addColorStop(1, 'rgba(0,0,0,0)');
// assignation des dégradés aux styles de remplissage et de pinceau
ctx.fillStyle = lingrad;
ctx.strokeStyle = lingrad2;
// dessin des formes
ctx.fillRect(10,10,130,130);
ctx.strokeRect(50,50,50,50);
}
[modifier] Un exemple d'utilisation de createRadialGradient
Dans cet exemple, quatre dégradés radiaux différents ont été définis. Comme on peut contrôler les points de départ et d'arrivée du dégradé, il est possible d'obtenir des effets plus complexes que dans les dégradés « classiques » qu'on peut voir, par exemple, dans Photoshop. (c'est-à-dire un dégradé avec un simple point central à le dégradé s'étend alentour dans une forme circulaire.)
Dans ce cas, le point de départ a été décalé légèrement du point d'arrivée pour obtenir un effet sphérique 3D. Il vaut mieux essayer d'éviter de laisser les cercles intérieurs et extérieurs se superposer parce que cela cause d'étranges effets qui sont difficiles à prédire.
La dernière couleur définie dans chacun des quatre dégradés est une couleur totalement transparente. Si vous voulez obtenir une belle transition entre celle-ci et la couleur précédente, les deux couleurs doivent à part cela être égales. Ce n'est pas évident en voyant le code parce que deux méthodes de couleurs CSS différentes ont été utilisées, mais dans le premier dégradé, #019F62 = rgba(1,159,98,1).
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
// Création des dégradés
var radgrad = ctx.createRadialGradient(45, 45, 10, 52, 50, 30);
radgrad.addColorStop(0, '#A7D30C');
radgrad.addColorStop(0.9, '#019F62');
radgrad.addColorStop(1, 'rgba(1,159,98,0)');
var radgrad2 = ctx.createRadialGradient(105, 105, 20, 112, 120, 50);
radgrad2.addColorStop(0, '#FF5F98');
radgrad2.addColorStop(0.75, '#FF0188');
radgrad2.addColorStop(1, 'rgba(255,1,136,0)');
var radgrad3 = ctx.createRadialGradient(95, 15, 15, 102, 20, 40);
radgrad3.addColorStop(0, '#00C9FF');
radgrad3.addColorStop(0.8, '#00B5E2');
radgrad3.addColorStop(1, 'rgba(0,201,255,0)');
var radgrad4 = ctx.createRadialGradient(0, 150, 50, 0, 140, 90);
radgrad4.addColorStop(0, '#F4F201');
radgrad4.addColorStop(0.8, '#E4C700');
radgrad4.addColorStop(1, 'rgba(228,199,0,0)');
// dessin des formes
ctx.fillStyle = radgrad4;
ctx.fillRect(0, 0, 150, 150);
ctx.fillStyle = radgrad3;
ctx.fillRect(0, 0, 150, 150);
ctx.fillStyle = radgrad2;
ctx.fillRect(0, 0, 150, 150);
ctx.fillStyle = radgrad;
ctx.fillRect(0, 0, 150, 150);
}
[modifier] Motifs
Dans l'un des exemples de la page précédente, nous avions utilisé une série de boucles pour créer un papier-peint à partir d'un motif. Il existe cependant une méthode beaucoup plus simple : la méthode createPattern.
createPattern(image, type)
Cette méthode prend deux arguments. Le premier est soit une référence à un objet Image ou à un autre élément canvas. Le second est une chaîne devant contenir l'une des valeurs suivantes : repeat, repeat-x, repeat-y et no-repeat.
Image ne fonctionne pas dans Firefox 1.5 (Gecko 1.8)On utilise cette méthode pour créer un objet Pattern qui est s'utilise de façon très similaire à ce que nous avons vu pour les dégradés plus haut.
Une fois un motif créé, il peut être assigné aux propriétés fillStyle ou strokeStyle properties.
var img = new Image(); img.src = 'uneimage.png'; var ptrn = ctx.createPattern(img, 'repeat')
Note : Contrairement à la méthode drawImage, il convient de vous assurer que l'image utilisée est chargée avant d'appeler cette méthode, ou le motif peut être dessiné incorrectement.
Note : Actuellement, Firefox supporte seulement la propriété repeat. Si vous choisissez autre chose, vous ne verrez aucun changement.
[modifier] Un exemple d'utilisation de createPattern
Dans ce dernier exemple, un motif a été créé et assigné à la propriété fillStyle. La seule chose notable est l'utilisation du gestionnaire onload de l'objet Image. Ceci permet de s'assurer que l'image est bien chargée avant d'être assignée au motif.
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
// création d'un nouvel objet image à utiliser comme motif
var img = new Image();
img.src = 'images/wallpaper.png';
img.onload = function() {
// création du motif
var ptrn = ctx.createPattern(img, 'repeat');
ctx.fillStyle = ptrn;
ctx.fillRect(0, 0, 150, 150);
}
}










