Il s'agit des translations, des changements d'échelle et des rotations, des inclinaisons.
Translation : le point d’origine du canevas est déplacé.
Les couleurs évoluent et sont à demi opaques.
L'élément canvas est dépourvu des attributs id, width & height donc le repère défini est ... ?
Puis l'instruction resetTransform() annule toutes les transformations ; donc l'origine du canevas est de nouveau
son coin haut gauche ; donc le carré avec les paramètres géométriques (X-cote,0,cote,cote) se positionne en haut à droite
du canevas.
Après un contexte.scale(2,2) l'instruction contexte.fillRect(100,100,100,100)
dessine et remplit un carré de 200 par 200 positionné à 200,200 de l'origine.
La balise canvas définit un repère de 400 par 400 ; l'attribut ID est absent.
On peut aussi changer l'orientation du contexte ou en d'autres termes effectuer une rotation des axes.
La méthode rotate() est argumentée par un angle exprimé en radians !
Observez le schéma ci-dessous qui est plus explicatif qu'un long discours. Ainsi si vous dessinez un carré suite à une rotation de 45° des axes il apparaitra en fait tel un losange !
Trois formes dans le canevas ci-dessus : un carré rouge puis un losange jaune et enfin un carré vert !
La balise canvas définit un repère de 400 par 300 ; l'attribut ID est absent.
Il s'agit d'un bon exemple de rotation après un changement d'origine.
La balise canvas du document définit un repère de 300 par 300 ; la toile est identifiée "canevas".
ctx.translate(X/2,Y/2) : à partir du moment que vous envisagez des rotations il est préférable que l'origine du
canevas soit son centre (et non pas le coin haut gauche).
Marquage des heures :
Marquage des minutes :
Affichage de l'aiguille (trotteuse) :
Rappel : la méthode rotate() est argumentée par un angle en radians.
Pour convertir des degrés en radians la formule est : Math.PI/180 *degrés.
J'ai déjà abordé ces méthodes mais dans un cas simple : deux contextes uniquement.
Cette méthode sauvegarde l'état du canevas dans sa globalité.
La méthode save() peut être invoquée autant de fois que nécessaire.
Cette commande rétablit le plus récent contexte sauvegardé (celui en haut de la pile).
Cinq carrés de 100 par 100 sont dessinés : 3 contours et 2 remplissages.
La balise canvas définit un repère de 400 par 400.
HG veut dire : haut gauche
Il s'agit d'une méthode récente mais très utile car elle définit un nouveau contexte de transformation
tout en annulant le précédent. Elle permet donc d'économiser des lignes de code en particulier
des instructions basées sur les méthodes save() & restore().
Syntaxe : setTransform(a, b, c, d, e, f)
Ci-dessous un document HTML contenant une 'toile'.
Remarquez le carré violet en haut à droite.
La balise canvas du document définit un repère de 600 par 600.
Vous allez être épaté par la concision du code ; je dessine 7 carrés de 100 par 100 positionnés au point 0,0.
Mais ils prennent des aspects et des positions très différents à cause des différents contextes.
H : horizontal ; V : vertical
Ne confondez pas SetTransform() avec transform().
Plutôt un petit exemple qu'un long discours.
Repère cartésien de 400 par 400 défini par la balise canvas.
Notez que les transformations se cumulent : les quatre rectangles s'agrandissent et leur inclinaison s'accentue.
Vous pouvez me contacter via Facebook pour questions & suggestions :
Page Facebook relative à mon site
Canvas : les transformations
La translation a déjà été évoquée à l'occasion de différents exemples.
Ce chapitre prépare ceux sur les animations. En effet les transformations sont à la base de nombreuses
animations. Un seul exemple : pour déplacer un objet 2D le plus simple est de le translater.
Les différentes méthodes que nous allons employer dans les exemples de ce chapitre :
Translations
Exemple
Six carrés décalés et un septième dans le coin haut droit du canevas.
Le code correspondant
La fonction JS :
function script1()
{
canevas = document.querySelector('canvas');
contexte = canevas.getContext('2d');
var X =canevas.width;
var Y =canevas.height;
console.log(X);
console.log(Y);
var delta = 20;
var cote = 50;
var rouge = 255; var vert = 0; var bleu = 0;
var couleur;;
contexte.globalAlpha = 0.5; // 50% opacité pour tous les tracés futurs
for (i=1; i<=6; i++)
{
rouge-=30 ; vert+=30; bleu+=30;
couleur = "rgb("+ rouge+","+vert+","+bleu+")" ;
contexte.fillStyle = couleur ;
contexte.fillRect(0,0,cote,cote) ;
contexte.translate(delta,delta) ; // déplacement origine pour rectangle suivant
} // fin for
contexte.resetTransform();
contexte.fillRect(X-cote,0,cote,cote);
}
script1(); //appel de la fonction
À chaque passage dans la boucle :
Changement d'échelle
Exemple complet
Le code correspondant
Le script correspondant :
function script2()
{
canevas = document.querySelectorAll('canvas')[1];
contexte = canevas.getContext('2d');
contexte.fillStyle ='red';
contexte.fillRect(0,0,100,100);
contexte.save(); //sauvegarde état initial canevas
contexte.scale(2,2);
contexte.fillStyle ='green';
contexte.fillRect(100,100,100,100);
contexte.restore(); //restauration état intial canevas
contexte.fillStyle ='yellow';
contexte.fillRect(100,100,100,100);
}
script2(); //appel fonction
La démarche :
Rotation de formes
Principes
Cette méthode fait pivoter les axes X et Y du repère dans le sens des aiguilles d'une montre autour du point d'origine.
Souvent cette rotation a été précédée d'une translation : le centre du canevas devenant l'origine.
Exemple
Le code correspondant
La fonction JS :
function script3()
{
canevas = document.querySelectorAll('canvas')[2];
contexte = canevas.getContext('2d');
contexte.fillStyle ='red';
contexte.fillRect(0,0,100,100);
contexte.save();
contexte.rotate(Math.PI/180 *45);
contexte.fillStyle ='yellow';
contexte.fillRect(200,0,100,100);
contexte.restore();
contexte.fillStyle ='green';
contexte.fillRect(300,100,100,100);
}
script3();
La démarche :
Un cadran de réveil
Ci-dessous un document HTML qui contient une 'toile' affichant le cadran d'une montre avec un aiguille (la trotteuse).
Le code de ce document
Le script
var canevas = document.querySelector("#canevas");
var ctx = canevas.getContext("2d");
var X =canevas.width;
var Y =canevas.height;
// l'origine devient le centre de la toile
ctx.translate(X/2,Y/2);
ctx.strokeStyle = "gold";
ctx.lineWidth = 4;
// marques heures
for (var i=0;i<12;i++)
{
ctx.beginPath();
// un trait tous les 30°
ctx.rotate(Math.PI/180 * 30);
ctx.moveTo(80,0);
ctx.lineTo(100,0);
ctx.stroke();
}
// marques minutes
ctx.lineWidth = 2;
for (i=0;i<60;i++)
{
ctx.beginPath();
// un trait tous les 6°
ctx.rotate(Math.PI/180 *6);
ctx.moveTo(90,0);
ctx.lineTo(100,0);
ctx.stroke();
}
// trotteuse
ctx.strokeStyle ="black";
ctx.lineWidth =3;
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(0,-100);
ctx.stroke();
Analyse du script
Il faut créer 12 traits : un trait tous les 30 degrés
Il faut créer 60 traits plus courts et moins épais : un trait tous les 6 degrés.
Il faut changer la couleur et l'épaisseur de contour, dessiner un trait à partir du centre du canevas.
Bien maitriser les méthodes save() & restore()
la méthode save()
Chaque invocation de la méthode save() ajoute une copie de l'état courant du canevas en haut de la pile.
Cet état courant du canevas est composé :
La méthode restore()
Cette méthode peut être évoquée autant de fois qu'il y a eu de commmandes save().
Un document HTML contenant un canevas
Le script
Dans le script je définis un rectangle nommé "carre" dont les paramètres géométriques sont : 0,0,100,100.
Puis je le dessine cinq fois mais dans des contextes différents.
function dessin()
{
var ctx = document.getElementById("canvas").getContext("2d");
ctx.strokeStyle ='olive';
ctx.lineWidth =5;
ctx.fillStyle ='rgba(0,0,0,0.3)'; // gris clair
var carre = new Path2D();
carre.rect(0,0,100,100);
ctx.stroke(carre); //premier dessin de carre
ctx.save(); // Sauvegarde contexte 0
ctx.translate(200,200) ;
// l'origine devient le centre du canevas
ctx.stroke(carre); // deuxième dessin de carre
ctx.save(); // sauvegarde contexte 1
ctx.rotate(Math.PI/180*45);
ctx.stroke(carre); // 3ième dessin de carre
ctx.restore(); // restauration contexte 1
ctx.fill(carre); // 4ième dessin de carre
ctx.restore(); // restauration contexte 0
ctx.fill(carre); // 5ième dessin de carré
}
dessin();
La démarche :
"Cerise sur le gâteau" : la méthode setTransform()
Mais sa syntaxe est un peu délicate ...
Six paramètres
Sens des différentes lettres :
Exemple
Le code
Le script
const canvas = document.getElementById('canevas');
const ctx = canvas.getContext("2d");
ctx.lineWidth =3;
X=canvas.width;
ctx.strokeStyle = 'red';
ctx.strokeRect(0,0,100,100);
ctx.setTransform(2,0,0,2,0,0); // doublement échelle
ctx.strokeStyle ='green';
ctx.strokeRect(0,0,100,100);
ctx.setTransform(1,0,0,1,150,150); // translation et retour à échelle 1
ctx.strokeStyle ='navy';
ctx.strokeRect(0,0,100,100);
ctx.setTransform(1,0.5, 0,1,250,250); // inclinaison et translation
ctx.strokeStyle ='black';
ctx.strokeRect(0,0,100,100);
ctx.setTransform(1,0,0.5, 1,300,300); // inclinaison et translation
ctx.strokeStyle ='orange';
ctx.strokeRect(0,0,100,100);
ctx.setTransform(1,-0.5,-0.5, 1, 400, 400);
ctx.strokeStyle ='yellow';
ctx.strokeRect(0,0,100,100);
ctx.resetTransform();
ctx.strokeStyle ='purple';
ctx.strokeRect(X-100,0, 100, 100);
Les différentes transformations :
Valeurs par défaut pour les paramètres a & d : 1
Valeurs par défaut pour les paramètres e & f : 0
Valeur par défaut pour les paramètres b & c : 0
Remarque
Avec la méthode historique transform(), le précédent contexte n'est pas annulé ; il a un phénomène cumulatif.
La méthode transform accepte les mêmes paramètres que setTransform().
On peut dire que SetTransform() équivaut à resetTransform() + transform().
Exemple de canevas basé sur la méthode transform()
Le script
const canvas = document.getElementById("canevas");
const ctx = canvas.getContext("2d");
ctx.fillStyle = "olive";
ctx.fillRect(0, 0, 300,80)
ctx.transform(1.1, 0.3, -0.3, 1.1, 30, 10);
ctx.fillStyle = "green";
ctx.fillRect(0, 0, 300, 80);
ctx.transform(1.1, 0.3, -0.3, 1.1, 30, 10);
ctx.fillStyle = "lime";
ctx.fillRect(0, 0, 300, 80);
ctx.transform(1.1, 0.3, -0.3, 1.1, 30, 10);
ctx.fillStyle = "black";
ctx.fillRect(0, 0, 300, 80);
En effet à chaque fois l'échelle 1.1 tant en H qu'en V et une inclinaison 0.3 tant en H qu'en V et aussi
une translation tant en H qu'en V.