Toile détaillée 01 - Dessiner des graphiques de base

Maintenant que nous avons configuré l'environnement de canevas, nous pouvons découvrir comment dessiner sur le canevas. À la fin de cet article, vous aurez appris à dessiner des rectangles, des triangles, des lignes, des arcs et des courbes, en vous familiarisant avec ces formes de base. Avant de dessiner des objets sur Canvas, vous devez maîtriser le chemin. Voyons comment le faire.

# grille

Avant de commencer à dessiner, nous devons comprendre la grille de toile (grille de toile) et l'espace de coordonnées. Le modèle HTML de la page précédente comporte un élément canvas d'une largeur de 150 pixels et d'une hauteur de 150 pixels. Comme indiqué à droite, l'élément canvas est couvert par une grille par défaut. En règle générale, une cellule de la grille équivaut à un pixel de l'élément canvas. Le point de départ de la grille est le coin supérieur gauche (coordonnées (0,0)). Tous les éléments sont positionnés par rapport à l'origine. Par conséquent, les coordonnées du coin supérieur gauche du carré bleu de la figure sont x pixels à partir de la gauche (axe X) et y pixels à partir du haut (axe Y) (les coordonnées sont (x, y)). À la fin de la leçon, nous allons traduire l'origine en différentes coordonnées, faire pivoter le maillage et mettre à l'échelle. Maintenant, nous utilisons toujours les paramètres d'origine.

#dessiner un rectangle

Contrairement à SVG, canvas ne prend en charge que deux formes de dessin graphique : les rectangles et les chemins (segments de ligne reliés par une série de points). Tous les autres types de graphiques sont formés en combinant un ou plusieurs chemins. Cependant, nous avons de nombreuses méthodes de génération de chemin qui permettent de dessiner des graphiques complexes.

Tout d'abord, nous revenons au dessin du rectangle. Canvas propose trois méthodes pour dessiner des rectangles :

fillRect(x, y, largeur, hauteur)

dessiner un rectangle plein

strokeRect(x, y, largeur, hauteur)

dessiner une bordure rectangulaire

clearRect(x, y, largeur, hauteur)

Effacez la zone rectangulaire spécifiée et rendez la partie effacée complètement transparente.

Chacune des méthodes fournies ci-dessus contient les mêmes paramètres. x et y spécifient les coordonnées du coin supérieur gauche (par rapport à l'origine) du rectangle dessiné sur le canevas. largeur et hauteur définissent les dimensions du rectangle.

La fonction draw() ci-dessous est obtenue à partir de la page précédente, utilisons maintenant les trois fonctions ci-dessus.

#Exemple rectangulaire

function draw() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext) {
    var ctx = canvas.getContext('2d');

    ctx.fillRect(25, 25, 100, 100);
    ctx.clearRect(45, 45, 60, 60);
    ctx.strokeRect(50, 50, 50, 50);
  }
}

La fonction fillRect() dessine un carré noir avec une longueur de côté de 100px. La fonction clearRect() efface un carré de 60 x 60 pixels du centre du carré , puis strokeRect() génère une bordure carrée de 50 x 50 dans la zone dégagée .

Ensuite, nous pouvons voir les deux méthodes facultatives de clearRect(), puis nous saurons comment modifier la couleur de remplissage et la couleur de trait des graphiques rendus.

Différent de la fonction de chemin qui sera introduite dans la section suivante, les trois fonctions ci-dessus apparaîtront sur le canevas immédiatement après le dessin et prendront effet immédiatement.

#rectangle _

Trois méthodes supplémentaires pour dessiner des rectangles directement sur le canevas, comme nous avons commencé par dessiner des rectangles, ont également la méthode rect(), qui ajoute un chemin de rectangle au chemin actuel.

rect(x, y, largeur, hauteur)

Dessinez un rectangle dont les coordonnées du coin supérieur gauche sont (x, y), la largeur et la hauteur sont la largeur et la hauteur.

Lorsque cette méthode est exécutée, la méthode moveTo() définit automatiquement le paramètre de coordonnées (0,0). Autrement dit, le trait actuel est automatiquement réinitialisé aux coordonnées par défaut.

# tracer le chemin

L'élément de base d'un graphe est un chemin. Un chemin est un ensemble de points de différentes formes reliés par des segments de ligne ou des courbes de différentes couleurs et largeurs. Un chemin, voire un sous-chemin, est fermé. Dessiner des formes avec des chemins nécessite quelques étapes supplémentaires.

  1. Tout d'abord, vous devez créer le point de départ du chemin.
  2. Ensuite, vous utilisez la commande de dessin pour dessiner le chemin.
  3. Ensuite, vous fermez le chemin.
  4. Une fois le chemin généré, vous pouvez rendre la forme en traçant ou en remplissant la zone du chemin.

Voici les fonctions à utiliser :

débutChemin()

Créez un nouveau chemin. Après sa génération, la commande de dessin graphique est dirigée vers le chemin pour générer le chemin.

fermerChemin()

Après avoir fermé le chemin, les commandes de dessin graphique sont redirigées vers le contexte.

accident vasculaire cérébral()

Dessinez le contour de la figure à travers la ligne.

remplir()

Génère une forme solide en remplissant la zone de contenu du chemin.

La première étape de la génération d'un chemin s'appelle beginPath(). Essentiellement, un chemin est composé de nombreux sous-chemins, tous dans une liste, et tous les sous-chemins (lignes, arcs, etc.) constituent le graphe. Et chaque fois que cette méthode est appelée, la liste est effacée et réinitialisée, puis nous pouvons redessiner de nouveaux graphiques.

Remarque :  Le chemin actuel est vide, c'est-à-dire qu'après avoir appelé beginPath(), ou lorsque le canevas vient d'être créé, la première commande de construction de chemin est généralement considérée comme moveTo(), quelle qu'elle soit. Pour cette raison, vous spécifiez presque toujours votre emplacement de départ après avoir défini le chemin.

La deuxième étape consiste à appeler la fonction pour spécifier le chemin de dessin, ce que nous verrons plus loin dans cet article.

Le troisième est le chemin fermé closePath(), qui n'est pas obligatoire. Cette méthode ferme la forme en traçant une ligne du point actuel au point de départ. Si le graphe est déjà fermé, c'est-à-dire que le point courant est le point de départ, cette fonction ne fait rien.

Remarque :  lorsque vous appelez la fonction fill(), toutes les formes non fermées seront automatiquement fermées, vous n'avez donc pas besoin d'appeler la fonction closePath(). Mais il ne sera pas fermé automatiquement lors de l'appel de stroke().

# dessine un triangle

Par exemple, le code pour dessiner un triangle est le suivant :

function draw() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext) {
    var ctx = canvas.getContext('2d');

    ctx.beginPath();
    ctx.moveTo(75, 50);
    ctx.lineTo(100, 75);
    ctx.lineTo(100, 25);
    ctx.fill();
  }
}

#coups en mouvement

Une fonction très utile qui ne dessine rien et qui fait partie de la liste de chemins décrite ci-dessus est moveTo(). Ou vous pouvez imaginer travailler sur du papier, avec la pointe d'un stylo ou d'un crayon se déplaçant d'un point à un autre.

déplacer vers (x, y)

Déplacez le trait aux coordonnées spécifiées x et y.

Après l'initialisation du canevas ou l'appel de beginPath(), vous définissez généralement le point de départ à l'aide de la fonction moveTo(). Nous pouvons également utiliser moveTo() pour dessiner des chemins discontinus. Jetez un œil à l'exemple de smiley ci-dessous. J'ai marqué l'endroit où la méthode moveTo() (en ligne rouge) est utilisée.

Vous pouvez l'essayer avec l'extrait de code ci-dessous. Copiez-le simplement dans la fonction draw() précédente.

function draw() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext){
    var ctx = canvas.getContext('2d');

    ctx.beginPath();
    ctx.arc(75, 75, 50, 0, Math.PI * 2, true); // 绘制
    ctx.moveTo(110, 75);
    ctx.arc(75, 75, 35, 0, Math.PI, false);   // 口 (顺时针)
    ctx.moveTo(65, 65);
    ctx.arc(60, 65, 5, 0, Math.PI * 2, true);  // 左眼
    ctx.moveTo(95, 65);
    ctx.arc(90, 65, 5, 0, Math.PI * 2, true);  // 右眼
    ctx.stroke();
  }
}

#ligne _

Pour tracer une ligne droite, la méthode lineTo() doit être utilisée.

ligneVers(x, y)

Dessine une ligne depuis la position actuelle jusqu'aux positions x et y spécifiées.

Cette méthode a deux paramètres : x et y, représentant le point dans le système de coordonnées où la ligne se termine. Le point de départ est relatif au chemin tracé précédent, le point de fin du chemin précédent est le point de départ suivant, etc. . . Le point de départ peut également être modifié par la fonction moveTo().

L'exemple suivant dessine deux triangles, l'un rempli et l'autre barré.

function draw() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext){
  var ctx = canvas.getContext('2d');

  // 填充三角形
  ctx.beginPath();
  ctx.moveTo(25, 25);
  ctx.lineTo(105, 25);
  ctx.lineTo(25, 105);
  ctx.fill();

  // 描边三角形
  ctx.beginPath();
  ctx.moveTo(125, 125);
  ctx.lineTo(125, 45);
  ctx.lineTo(45, 125);
  ctx.closePath();
  ctx.stroke();
  }
}

Cela commence par appeler la fonction beginPath() pour se préparer à dessiner un nouveau chemin de forme. Utilisez ensuite la fonction moveTo() pour vous déplacer vers la position cible. Ensuite, ci-dessous, les deux segments de ligne sont dessinés pour former les deux côtés du triangle.

#arc _

Pour dessiner un arc ou un cercle, nous utilisons la méthode arc(). Bien sûr, vous pouvez utiliser arcTo(), mais l'implémentation de ceci n'est pas si fiable, nous ne l'introduirons donc pas ici.

arc(x, y, radius, startAngle, endAngle, anti-horaire)

Dessinez un arc (cercle) avec (x, y) comme centre et rayon comme rayon, de startAngle à endAngle, et générez selon la direction donnée par anti-horaire (la valeur par défaut est le sens horaire).

arcVers(x1, y1, x2, y2, rayon)

Dessinez un arc en fonction du point de contrôle et du rayon donnés, puis reliez les deux points de contrôle par une ligne droite.

Voici une introduction détaillée à la méthode de l'arc, qui comporte six paramètres : x, y sont les coordonnées du centre du cercle où l'arc est tracé. rayon est le rayon. Les paramètres startAngle et endAngle définissent les arcs de début et de fin en radians. Ceux-ci sont tous référencés sur l'axe des x. Le paramètre dans le sens inverse des aiguilles d'une montre est une valeur booléenne. Lorsqu'il est vrai, c'est dans le sens antihoraire, sinon dans le sens horaire.

Remarques :  L'unité de l'angle dans la fonction arc() est le radian et non le degré. L'expression js de l'angle et du radian :

Radians = (Math.PI/180)*angles.

L'exemple suivant est un peu plus compliqué que le précédent, et 12 angles différents et arcs remplis sont dessinés ci-dessous.

Les deux boucles for suivantes génèrent les coordonnées de ligne et de colonne (x, y) de l'arc. BeginPath() est appelé au début de chaque arc. Dans le code, les paramètres de chaque arc sont variables, mais en programmation réelle, nous n'avons pas besoin de le faire.

Les coordonnées x,y sont variables. Le rayon (radius) et l'angle de départ (startAngle) sont fixes. L'angle final (endAngle) commence à 180 degrés dans la première colonne (demi-cercle) et augmente de 90 degrés avec chaque colonne. La dernière colonne forme un cercle complet.

L'instruction dans le sens des aiguilles d'une montre agit sur les première et troisième lignes comme un arc dans le sens des aiguilles d'une montre, et dans le sens inverse des aiguilles d'une montre agit sur les deuxième et quatrième lignes comme un arc dans le sens inverse des aiguilles d'une montre. L'instruction if fait que les première et deuxième lignes tracent l'arc, et les deux lignes suivantes remplissent le chemin.

Remarque :  La taille de canevas requise pour cet exemple est légèrement supérieure à celle des autres exemples de cette page : 150 x 200 pixels.

function draw() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext){
    var ctx = canvas.getContext('2d');

    for(var i = 0; i < 4; i++){
      for(var j = 0; j < 3; j++){
        ctx.beginPath();
        var x = 25 + j * 50; // x 坐标值
        var y = 25 + i * 50; // y 坐标值
        var radius = 20; // 圆弧半径
        var startAngle = 0; // 开始点
        var endAngle = Math.PI + (Math.PI * j) / 2; // 结束点
        var anticlockwise = i % 2 == 0 ? false : true; // 顺时针或逆时针

        ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise);

        if (i>1){
          ctx.fill();
        } else {
          ctx.stroke();
        }
      }
    }
  }
}

#Utiliser la méthode arcTo

Voici un extrait de code simple pour dessiner un arc. Le point de base est bleu et les deux points de contrôle sont rouges.

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

ctx.setLineDash([])
ctx.beginPath();
ctx.moveTo(150, 20);
ctx.arcTo(150,100,50,20,30);
ctx.stroke();

ctx.fillStyle = 'blue';
// base point
ctx.fillRect(150, 20, 10, 10);

ctx.fillStyle = 'red';
// control point one
ctx.fillRect(150, 100, 10, 10);
// control point two
ctx.fillRect(50, 20, 10, 10);
//
ctx.setLineDash([5,5])
ctx.moveTo(150, 20);
ctx.lineTo(150,100);
ctx.lineTo(50, 20);
ctx.stroke();
ctx.beginPath();
ctx.arc(120,38,30,0,2*Math.PI);
ctx.stroke();

#Courbe de Bézier quadratique et courbe de Bézier cubique

Le prochain type de chemin très utile est la courbe de Bézier. Les courbes de Bézier quadratiques et cubiques sont très utiles et sont généralement utilisées pour dessiner des graphiques complexes et réguliers.

quadraticCurveTo(cp1x, cp1y, x, y)

Dessinez une courbe de Bézier quadratique, cp1x,cp1y est un point de contrôle, x,y est le point final.

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

Dessinez une courbe de Bézier cubique, cp1x, cp1y est le point de contrôle 1, cp2x, cp2y est le point de contrôle 2, x, y est le point final.

La figure de droite peut bien décrire la relation entre les deux. La courbe de Bézier quadratique a un point de départ (bleu), un point final (bleu) et un point de contrôle (rouge), tandis que la courbe de Bézier cubique a deux points de contrôle.

Les paramètres x, y sont les coordonnées du point final dans les deux méthodes. cp1x, cp1y est le premier point de contrôle en coordonnées, cp2x, cp2y est le deuxième point de contrôle en coordonnées.

Travailler avec des courbes de Bézier quadratiques et cubiques est quelque peu difficile car contrairement aux logiciels vectoriels comme Adobe Illustrators, les courbes que nous dessinons ne nous donnent pas de retour visuel direct. Il est donc très difficile de dessiner des graphiques complexes. Dans les exemples suivants, nous allons dessiner quelques graphiques simples et réguliers.Si vous avez du temps et plus de patience, vous pouvez également dessiner de nombreux graphiques complexes.

Les exemples suivants ne posent pas beaucoup de difficulté. Dans ces deux exemples, nous allons tracer des courbes de Bézier en continu, et enfin former des graphiques complexes.

#Courbe de Bézier quadratique

Cet exemple utilise plusieurs courbes de Bézier pour rendre une bulle de dialogue.

function draw() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext) {
    var ctx = canvas.getContext('2d');

    // 二次贝塞尔曲线
    ctx.beginPath();
    ctx.moveTo(75, 25);
    ctx.quadraticCurveTo(25, 25, 25, 62.5);
    ctx.quadraticCurveTo(25, 100, 50, 100);
    ctx.quadraticCurveTo(50, 120, 30, 125);
    ctx.quadraticCurveTo(60, 120, 65, 100);
    ctx.quadraticCurveTo(125, 100, 125, 62.5);
    ctx.quadraticCurveTo(125, 25, 75, 25);
    ctx.stroke();
   }
}

# Courbe de Bézier cubique

Cet exemple dessine une forme de cœur à l'aide de courbes de Bézier.

function draw() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext){
    var ctx = canvas.getContext('2d');

     //三次贝塞尔曲线
    ctx.beginPath();
    ctx.moveTo(75, 40);
    ctx.bezierCurveTo(75, 37, 70, 25, 50, 25);
    ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5);
    ctx.bezierCurveTo(20, 80, 40, 102, 75, 120);
    ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5);
    ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25);
    ctx.bezierCurveTo(85, 25, 75, 37, 75, 40);
    ctx.fill();
  }
}

#

#Utilisation combinée

Jusqu'à présent, chaque forme dans chacun des exemples n'a utilisé qu'un seul type de chemin. Cependant, dessiner un graphique ne limite pas le nombre et le type d'utilisation. Donc, dans un dernier exemple, combinons toutes les fonctions de chemin pour reproduire un jeu célèbre.

function draw() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext){
    var ctx = canvas.getContext('2d');

    roundedRect(ctx, 12, 12, 150, 150, 15);
    roundedRect(ctx, 19, 19, 150, 150, 9);
    roundedRect(ctx, 53, 53, 49, 33, 10);
    roundedRect(ctx, 53, 119, 49, 16, 6);
    roundedRect(ctx, 135, 53, 49, 33, 10);
    roundedRect(ctx, 135, 119, 25, 49, 10);

    ctx.beginPath();
    ctx.arc(37, 37, 13, Math.PI / 7, -Math.PI / 7, false);
    ctx.lineTo(31, 37);
    ctx.fill();

    for(var i = 0; i < 8; i++){
      ctx.fillRect(51 + i * 16, 35, 4, 4);
    }

    for(i = 0; i < 6; i++){
      ctx.fillRect(115, 51 + i * 16, 4, 4);
    }

    for(i = 0; i < 8; i++){
      ctx.fillRect(51 + i * 16, 99, 4, 4);
    }

    ctx.beginPath();
    ctx.moveTo(83, 116);
    ctx.lineTo(83, 102);
    ctx.bezierCurveTo(83, 94, 89, 88, 97, 88);
    ctx.bezierCurveTo(105, 88, 111, 94, 111, 102);
    ctx.lineTo(111, 116);
    ctx.lineTo(106.333, 111.333);
    ctx.lineTo(101.666, 116);
    ctx.lineTo(97, 111.333);
    ctx.lineTo(92.333, 116);
    ctx.lineTo(87.666, 111.333);
    ctx.lineTo(83, 116);
    ctx.fill();

    ctx.fillStyle = "white";
    ctx.beginPath();
    ctx.moveTo(91, 96);
    ctx.bezierCurveTo(88, 96, 87, 99, 87, 101);
    ctx.bezierCurveTo(87, 103, 88, 106, 91, 106);
    ctx.bezierCurveTo(94, 106, 95, 103, 95, 101);
    ctx.bezierCurveTo(95, 99, 94, 96, 91, 96);
    ctx.moveTo(103, 96);
    ctx.bezierCurveTo(100, 96, 99, 99, 99, 101);
    ctx.bezierCurveTo(99, 103, 100, 106, 103, 106);
    ctx.bezierCurveTo(106, 106, 107, 103, 107, 101);
    ctx.bezierCurveTo(107, 99, 106, 96, 103, 96);
    ctx.fill();

    ctx.fillStyle = "black";
    ctx.beginPath();
    ctx.arc(101, 102, 2, 0, Math.PI * 2, true);
    ctx.fill();

    ctx.beginPath();
    ctx.arc(89, 102, 2, 0, Math.PI * 2, true);
    ctx.fill();
  }
}

// 封装的一个用于绘制圆角矩形的函数。

function roundedRect(ctx, x, y, width, height, radius){
  ctx.beginPath();
  ctx.moveTo(x, y + radius);
  ctx.lineTo(x, y + height - radius);
  ctx.quadraticCurveTo(x, y + height, x + radius, y + height);
  ctx.lineTo(x + width - radius, y + height);
  ctx.quadraticCurveTo(x + width, y + height, x + width, y + height - radius);
  ctx.lineTo(x + width, y + radius);
  ctx.quadraticCurveTo(x + width, y, x + width - radius, y);
  ctx.lineTo(x + radius, y);
  ctx.quadraticCurveTo(x, y, x, y + radius);
  ctx.stroke();
}

Nous n'expliquerons pas le code ci-dessus en détail, car il est en fait assez facile à comprendre. Le point clé est que la propriété fillStyle et la fonction d'encapsulation (roundedRect() dans l'exemple) sont utilisées dans le contexte du dessin. L'utilisation de fonctions wrapper est très utile pour réduire la taille et la complexité du code.

Nous aborderons fillStyle plus en détail plus tard dans la leçon. Dans ce chapitre, tout ce que nous avons fait avec le style fillStyle a été de changer la couleur de remplissage du noir par défaut au blanc, puis à nouveau au noir.

# Objet Path2D

Comme nous l'avons vu dans l'exemple précédent, vous pouvez utiliser une série de commandes de tracé et de dessin pour "peindre" des objets sur le canevas. Pour simplifier le code et améliorer les performances, les objets Path2D sont disponibles dans les nouveaux navigateurs pour mettre en cache ou enregistrer les commandes de dessin afin que vous puissiez rapidement revoir les chemins.

Comment générer un objet Path2D ?

Chemin2D()

Path2D() renvoie un objet Path2D nouvellement initialisé (éventuellement avec un chemin comme variable - en créant une copie de celui-ci, ou avec une chaîne contenant les données du chemin SVG comme variable).

Toutes les méthodes de chemin telles que moveTo, rect, arc ou quadraticCurveTo etc., comme nous l'avons vu précédemment, peuvent être utilisées dans Path2D.

L'API Path2D ajoute addPath comme méthode pour combiner des chemins. Ceci est utile lorsque vous souhaitez créer des objets à partir de plusieurs éléments. Par exemple:

Path2D.addPath(chemin [, transformation])

Ajoute un chemin au chemin actuel (éventuellement en ajoutant une matrice de transformation).

# Exemple Path2D

Dans cet exemple, nous avons créé un rectangle et un cercle. Ils sont tous stockés en tant qu'objets Path2D pour être utilisés ultérieurement. Avec la nouvelle API Path2D, plusieurs méthodes ont été mises à jour pour utiliser l'objet Path2D au lieu du chemin actuel. Ici, le trait et le remplissage avec les paramètres de chemin peuvent dessiner des objets sur le canevas.

function draw() {
  var canvas = document.getElementById('canvas');
  if (canvas.getContext){
    var ctx = canvas.getContext('2d');

    var rectangle = new Path2D();
    rectangle.rect(10, 10, 50, 50);

    var circle = new Path2D();
    circle.moveTo(125, 35);
    circle.arc(100, 35, 25, 0, 2 * Math.PI);

    ctx.stroke(rectangle);
    ctx.fill(circle);
  }
}

#Utiliser les chemins SVG

Une autre fonctionnalité puissante de la nouvelle API Path2D est l'utilisation de données de chemin SVG pour initialiser les chemins sur le canevas. Cela vous permettra de récupérer des chemins et de les réutiliser comme SVG ou canvas.

Ce chemin se déplacera d'abord vers le point (M10 10) puis de 80 unités horizontalement (h 80), puis de 80 unités vers le bas (v 80), puis de 80 unités vers la gauche (h -80) et de revenir au point de départ (z) .

var p = new Path2D("M10 10 h 80 v 80 h -80 Z");

Je suppose que tu aimes

Origine blog.csdn.net/qq_59747594/article/details/131350748
conseillé
Classement