Récemment, l'auteur a une exigence. Le contenu de l'exigence est le suivant : un groupe de texte est affiché autour de l'anneau. Le texte entoure l'anneau. Chaque mot correspond à un petit point bleu autour de l'anneau. passez la souris sur le petit point bleu au-dessus de l’anneau fera rayonner le triangle puis affichera le texte. Jetons d’abord un coup d’œil à l’effet d’animation !
Comme le montre l'image ci-dessus, lorsque la souris est placée sur le petit point bleu correspondant, un rayon en forme de triangle doit être émis, et le texte correspondant est affiché à l'extérieur du triangle, et le petit point bleu devient un petit point blanc.
Lorsque l'utilisateur saisit du contenu ci-dessus, le contenu est ajouté autour de l'anneau ci-dessous. Comme le montre l'image ci-dessus.
L'idée originale de l'auteur était d'utiliser du CSS pour l'implémenter, tout comme le menu secondaire dynamique dans l'image ci-dessous.
Cependant, étant donné que le contenu sur le bord de l'anneau est variable et doit être positionné autour de l'anneau, CSS peut être difficile à mettre en œuvre. Alors wow, l'auteur a décidé d'utiliser la toile pour y parvenir. (L'auteur n'a appris la toile que récemment. S'il y a quelque chose qui ne va pas, j'accepte vos corrections).
Processus de mise en œuvre :d'abord:
La partie html du code est la suivante :
<canvas style=margin-left: 50px;padding-top: 20px; display:block id=canvas > La version actuelle de votre navigateur ne prend pas en charge le canevas</canvas>
Les étapes spécifiques de mise en œuvre sont les suivantes :
1. Dessinez un grand cercle.
Utilisez la méthode canvas : context.arc(x, y, radius, startAngle, endAngle [, antihoraire]);
x, y : coordonnées du centre du cercle, radius : rayon du centre du cercle, startAngle : dessin du radian de départ, endAngle : dessin du radian de fin, [, antihoraire] : paramètre optionnel, s'il faut dessiner l'arc dans le sens horaire ou antihoraire.
Pour faciliter le dessin, l'auteur a déplacé l'origine de la toile du coin supérieur gauche précédent vers le centre de la toile.
Le rayon de l'anneau calculé par l'auteur est r-80
canvas.width = 500canvas.height = 500//Calculez le rayon du centre du canevas soit r = 500 / 2//Déplacez l'origine du canevas au centre du canevas lorsque l'interface est initialisée ctx.translate(r ,r) //Déplacez le pinceau pour arrondir
Le code spécifique est le suivant :
//Initialisation du canevas let canvas = document.getElementById('canvas')let ctx= canvas.getContext('2d')let ratio = getPixelRato(ctx)canvas.width = 500canvas.height = 500//Calculer le rayon du centre du canevas soit r = 500 / 2// Lorsque l'interface est initialisée, déplacez l'origine du canevas au centre du canevas ctx.translate(r,r) //Déplacez le pinceau vers le cercle ctx.lineWidth = 3; //Définissez la largeur de ligne du pinceau ctx.beginPath(); //Démarrez le pinceau//Dessinez la couleur du bord dégradé du cercle var arcColor = ctx.createLinearGradient(-170, -170, 0, 170)arcColor.addColorStop(0, '#8ec1ff')arcColor.addColorStop(0.2, '#83beff')arcColor.addColorStop(0.5, '#75b1ff')arcColor.addColorStop(0.7,'#5998ff')arcColor.addColorStop(1, '#2065ff')ctx .StrokeStyle= arcColor;//Définir la couleur du pinceau ctx.arc(0,0,r - 80,0,2*Math.PI,false) //Dessiner un cercle, coordonnées 0,0, rayon 250-80, cercle complet (0 -360 degrés), false signifie dans le sens des aiguilles d'une montre ctx.closePath()ctx.Stroke() //Dessin
Les résultats du dessin sont les suivants
2. Dessinez l'image de fond au milieu de l'anneau (l'origine du canevas actuel est le centre du canevas)
drawImage(image, dx, dy, dLargeur, dHauteur)
image : ressource d'image Canvas, telle qu'une image <img>, une image SVG, l'élément Canvas lui-même, etc.
dx, dy : prévoyez une zone sur la toile pour placer des images. dx est les coordonnées horizontales et verticales du coin supérieur gauche de cette zone.
dWidth, dHeight : prévoyez une zone sur la toile Canvas pour placer des images, la largeur et la hauteur de cette zone.
Les coordonnées suivantes sont calculées par l'auteur
let image = new Image()image.src = 'image/quan.png'image.onload = () => { // Déplacer l'origine au centre ctx.drawImage(image,-140,-140,280,280)}
Les résultats du dessin sont les suivants :
3. Dessinez du texte et des petits points sur l'anneau (l'origine du canevas actuel est le centre du canevas)
Cibles de dessin pour le texte et les petits points :
3.1 Les petits points sont affichés uniformément sur le grand anneau
3.2 Le texte est un peu dispersé en dehors des petits points
Solution:1. L'auteur utilise un tableau pour stocker les mots actuels
let textArr = ['Grande mer et ciel','Capacités techniques','Des fonds solides','Contrôle de la maintenance','Vivre et travailler dans la paix et le contentement','Observez les fleurs','Terminez la touche finale',' Débarrassez-vous des scories','Allez contre le vent','évolution de carrière']
2. Étant donné que le nombre de petits points et le nombre de mots sont les mêmes, leur nombre correspond à la longueur du tableau textArr ci-dessus.
3. Le radian d'un cercle complet est 2π Pour que les petits points divisent également l'anneau, l'auteur calcule d'abord le radian du point où se trouve chaque petit point.
for(let i = 0;i<lengths;i++){ // Calculer les radians let rad = 2*Math.PI/lengths*i}
4. Selon les fonctions trigonométriques, les coordonnées (x, y) du petit point actuel sur la toile peuvent être calculées (l'origine de la toile actuelle est le centre de la toile)
Parmi eux, la relation entre le radian, le petit point, l'anneau, le rayon de l'anneau et l'origine de la toile, l'auteur a dessiné une image pour les décrire.
Calculez les coordonnées du texte :
// Calculer les coordonnées du centre du petit cercle soit x = (r - 40)*Math.cos(rad)let y = (r - 40)*Math.sin(rad)
Calculez les coordonnées du petit point : Comme le centre du petit point doit tomber sur l'anneau, les coordonnées horizontales et verticales calculées sont,
// Calculer les coordonnées du texte let x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad)
Le code spécifique est le suivant :
// Dessine le texte ctx.font = '13px Arial'ctx.textAlign = 'center'ctx.textBaseline = 'middle'ctx.fillStyle=#000000let lengths = textArr.lengthtextArr.forEach(function(text,i){ //radians soit rad = 2*Math.PI/lengths*i // Calculer les coordonnées du centre du petit cercle soit x = (r - 40)*Math.cos(rad) let y = (r - 40)*Math.sin(rad) ctx.fillText(text,x+0.5,y+0.5)});// Dessine des petits points pour(let i = 0;i<lengths;i++){ // // soit rad = 2*Math.PI/lengths*i soit x = (r - 80)*Math.cos(rad) let y = (r - 80)*Math.sin(rad)// // Dessine des petits points gris translucides sur le bord ctx.beginPath() ctx.fillStyle = 'rgba(226,235,250, 0.8)' ctx.arc(x,y,8,0,2*Math.PI,false) ctx.closePath() ctx.fill() // Dessine des petits points bleus ctx.beginPath() ctx.fillStyle = '#208fe5' ctx.arc(x,y,4,0,2*Math.PI,false) ctx.closePath( ) ctx .remplir() }
Les résultats du dessin sont les suivants :
4. Dessinez un triangle à l'extérieur de chaque petit point (l'origine du canevas actuel est le centre du canevas)
4.1 Parce que vous souhaitez dessiner une forme de triangle, l'idée de dessiner un triangle est de tracer des lignes des deux côtés avec le centre du petit point actuel comme point de départ, puis d'utiliser ctx.fill() pour fermer la forme et remplissez l'intérieur de couleurs dégradées.
Dessinez un triangle : les coordonnées sont calculées par elles-mêmes. L'auteur ajoute et soustrait 35 en abscisse et 70 en ordonnée (comme tu veux, hahaha)
//Démarrez le pinceau ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath()
Dessinez le texte sous le triangle : (Pour le distinguer du texte précédent, j'ai utilisé du rouge pour mon texte ici)
ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75)
Le code spécifique est le suivant :
for(let i = 0;i<lengths;i++){ // // soit rad = 2*Math.PI/lengths*i soit x = (r - 80)*Math.cos(rad) soit y = (r - 80)*Math.sin(rad) // // Dessine le triangle // // ctx.rotate( -Math.PI / 4) ctx.beginPath() //Démarrez le pinceau ctx.moveTo(x,y) ctx.lineTo(x-35,y+70) ctx.lineTo(x+35,y+70) ctx.closePath() // // Définir le dégradé de couleur- - ->Ajouter de la couleur du centre aux deux côtés var sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0.5)') sColor.addColorStop(0.6,'rgba(83,183,243,0.5)') sColor.addColorStop(0.7,'rgba(129,200,224,0.5)') sColor.addColorStop(0.8,'rgba(130,219,251,0.5)') sColor.addColorStop(1,'rgba(195,228,223,0.5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75)}
Les résultats du dessin sont les suivants :
4.2 L'exigence est que la direction de chaque triangle doit s'étendre vers l'extérieur, et maintenant la direction des triangles est vers le bas, vous devez donc maintenant utiliser la méthode de rotation du canevas.
ctx.save() ctx.translate(x,y) // L'angle de rotation est centré sur chaque petit point ctx.rotate( rad - Math.PI/2 ) // Parce que le petit point ctx.translate(- x, - y) . Omettez le code pour dessiner des triangles et du texte.
Le calcul montre qu'en prenant le centre du petit point comme point de départ de la rotation, l'arc de rotation du triangle devrait être l'arc du petit point actuel moins π/2, car la position de départ de la rotation est toujours commence à partir de la direction positive de l'axe des coordonnées x, c'est-à-dire qu'il commence à 0 radians, mais maintenant les triangles sont tous à π/2 radians, donc :
Radian de rotation = Radian du petit point - π/2
N'oubliez pas d'utiliser la méthode de stockage d'état Canvas save() lors de la rotation.
recovery() fait apparaître à son tour l'état Canvas stocké du haut de la pile. S'il n'y a pas d'état Canvas stocké, il n'y aura aucun changement dans l'exécution de cette méthode.
N'oubliez pas d'utiliser la méthode restaurer() à la fin. À ce stade, l'auteur a versé des larmes de regret. . .
Code spécifique :
for(let i = 0;i<lengths;i++){ // // soit rad = 2*Math.PI/lengths*i soit x = (r - 80)*Math.cos(rad) soit y = (r - 80)*Math.sin(rad) // Dessine un triangle s ctx.save() // L'angle de rotation est centré sur chaque petit point car les petits points sont au début ctx.translate(x,y) ctx.rotate( rad - Math.PI/2 ) ctx.translate(-x, -y) // Démarre le pinceau ctx.beginPath() ctx.moveTo(x,y) ctx.lineTo(x-35,y+ 70 ) ctx.lineTo(x+35,y+70) ctx.closePath() //Définir le dégradé de couleur--->Ajouter une variable de couleur du centre vers les deux côtés sColor = ctx.createLinearGradient (x,y,x+18,y+50) sColor.addColorStop(0,'rgba(106,128,243,0.5)') sColor.addColorStop(0.6,'rgba(83,183,243,0.5)') sColor.addColorStop(0.7,'rgba(129,200,224,0.5)') sColor.addColorStop(0.8,'rgba(130,219,251,0.5)') sColor.addColorStop(1,'rgba(195,228,223,0.5)') ctx.fillStyle= sColor ctx.fill() ctx.fillStyle= '#e3211c' ctx.fillText(textArr[i],x,y+75) ctx.restore()}
Tracez le résultat :
Regardez de plus près, quoi ? ? ? Certains textes sont à l'envers en raison de problèmes de rotation. Grâce à l'observation, le résultat est que lorsque le radian est supérieur à π, le texte est à l'envers.
Il est temps d'écrire une vague de jugements. . . .
Comment faire pivoter le texte :
function rotateContext(ctx, x, y, degré) { // Rotation du texte ctx.translate(x, y) // ctx.rotate(degré * Math.PI / 180) ctx.rotate(degré) ctx.translate(-x , -y) }
Déterminer les petits points dont le radian est supérieur à π
if (rad > Math.PI) { // Comme le texte doit être affiché sur le bord du triangle, le texte doit pivoter avec le triangle afin qu'il puisse toujours être maintenu sur le // bord du triangle après la rotation. , le texte apparaîtra lorsque le radian est supérieur à π. Inversez le problème, donc faites pivoter le texte ctx.save() ctx.beginPath() // Faites pivoter le texte rotateContext(ctx, x, y+75, Math.PI) ctx.font = '13px Arial' ctx.textAlign = 'center' ctx.fillStyle = #ff2238 ctx.fillText(textArr[i], x, y+ 75) ctx.restore()} else { ctx.fillStyle = '#ff2238' ctx.fillText(textArr[i ], x, y + 75)}
Les résultats du dessin sont les suivants :
Dans l'attente de la victoire, nous avons presque réussi. Au moins, nous avons un schéma approximatif. La révolution n'a pas encore réussi, et les camarades doivent encore travailler dur ! !
5. Voici l'implémentation. Lorsque la souris est sur le petit point, le triangle sur le bord et le texte sur le bord du triangle sont affichés, mais le texte sur le bord du cercle n'est pas affiché.
Idée:1. Liez l'événement d'entrée de la souris au canevas
2. Déterminez si les coordonnées de la position actuelle de la souris sur le canevas sont égales aux coordonnées proches d'un petit point. Si tel est le cas, affichez le triangle correspondant au petit point.
5.1 Lier l'événement mousemove au canevas : la souris est au-dessus de l'événement
canvas.addEventListener('mousemove',clickEvent)
5.2 Calculer les coordonnées actuelles de la souris sur la toile
La méthode de calcul est la suivante : utilisez les coordonnées actuelles de la souris sur le DOM pour soustraire la distance depuis la gauche ou le haut du canevas pour calculer la distance du canevas.
La méthode drawOne dans la figure ci-dessous est la méthode de dessin, qui sera abordée plus loin dans l'article.
function clickEvent() { // Les coordonnées de la position de la souris let x = event.clientX - canvas.getBoundingClientRect().left let y = event.clientY - canvas.getBoundingClientRect().top drawOne(x,y)}
5.3, car les coordonnées de la souris sur le canevas calculées ci-dessus sont calculées avec le coin supérieur gauche du canevas comme origine, mais l'origine du canevas actuel s'est déjà déplacée vers le centre du canevas (250,250), donc lorsqu'il est utilisé pour déterminer si un clic est constitué de petits points Vous devez soustraire 250 des coordonnées horizontales et verticales pour comparer avec les coordonnées du petit point sur la toile actuelle. Lorsque j'ai porté mon jugement, j'ai trouvé un problème. Je ne sais pas pourquoi il y a une différence dans la direction y. de l'auteur est 260 au lieu de 250. L'auteur a donc soustrait 260 dans la direction y.
Le code est le suivant :
Parmi eux, Cx, Cy sont les coordonnées de la souris sur le canevas (le coin supérieur gauche du canevas est l'origine), x, y sont les coordonnées du petit point actuel,
L'auteur a directement calculé la position de 15 pixels près du centre du petit point, et tous les triangles ont été affichés et le petit point est devenu blanc.
Le plus important est que vous devez effacer le canevas précédent à chaque fois que vous redessinez : n'oubliez pas d'utiliser la méthode clearRect pour effacer le canevas
let XX = Cx - 250let YY = Cy- 260let leftX = x - 15 let rightX = x + 15let topY = y - 15let bottomY = y + 15if (XX >= leftX && XX <= rightX && YY <= bottomY && YY > = topY ) {//C'est cliqué. . . . . . //Écrivez le code du dessin au milieu}
Le code est suivi d'un lien :
6. Définissez une entrée sur l'interface et liez l'événement de changement à l'entrée.
Implémentation : L'interface est redessinée à chaque fois que la valeur de l'entrée change.
code html :
<input type=text id=inpt style=margin-left: 100px;margin-top: 50px placeholder=Veuillez entrer...>
code js :
let inpt = document.getElementById('inpt') inpt.addEventListener('change', function () { if (inpt.value !== '') { textArr.push(inpt.value) drawAll(2) //Ceci La méthode est la méthode du dessin, le code source sera donné plus loin dans l'article}})
7. Il y a un problème. Chaque fois que vous cliquez sur l'interface et que vous redessinez l'interface, une situation clignote.
Comme indiqué ci-dessous :
Chaque fois que vous glissez, car les coordonnées de la souris changent, vous devez effacer le contenu autour de l'anneau et le redessiner. Vous devez donc effacer le canevas pour obtenir des effets dynamiques.
clearRect() est très couramment utilisé dans le dessin d'animation Canvas. Il efface en continu le contenu du canevas, puis le dessine pour former un effet d'animation.
clearRect() peut rendre transparente une zone rectangulaire dans le canevas de l'élément Canvas.
context.clearRect(x, y, largeur, hauteur);
x, y : coordonnées x, y du coin supérieur gauche du rectangle.
width, height : la largeur et la hauteur de la zone rectangulaire dégagée.
Puisque clearRect() ne peut effacer que la zone rectangulaire du canevas, chaque fois qu'elle est effacée, l'image d'arrière-plan au milieu sera effacée ensemble.
Par conséquent, l'image d'arrière-plan doit être rechargée à chaque fois, et le chargement de l'image prend un certain temps, elle clignote donc à chaque fois qu'elle apparaît.
Solution:drawImage(image, dx, dy, dLargeur, dHauteur)
Le paramètre image : ressource d'image Canvas, telle que l'image <img>, l'image SVG, l'élément Canvas lui-même, etc.
Ensuite, vous pouvez utiliser un autre canevas pour mettre en cache les images.
Utilisez un canevas supplémentaire pour dessiner l'image d'arrière-plan, mais pour ce canevas non affiché dans l'interface : display:none, puis utilisez-le pour effacer le canevas et restituer directement l'objet canevas mis en cache au milieu du canevas à afficher, c'est-à-dire c'est-à-dire qu'il n'est pas nécessaire de charger les images une fois. Cela prend du temps.
code html :
<canvas width=280 height=280 style=margin-left: 50px;padding-top: 20px; display:none id=canvas2> </canvas>
code js :
//Utilisez la mise en cache pour résoudre le problème de clignotement des images redessinées var tempCanvas = document.getElementById('canvas2')const tempCtx = tempCanvas.getContext('2d')tempCanvas.width = 280; tempCanvas.height = 280let image = new Image( )image.src = 'image/quan.png'image.onload = () => { // L'origine se déplace vers le centre tempCtx.drawImage(image,0,0,280,280)}
Après avoir effacé le canevas, dessinez directement le canevas:tempCanvas mis en cache lorsque vous redessinez l'image.
// Dessine le canevas mis en cache directement sur l'interface (l'interface du pneu intermédiaire est mise en cache) ctx.drawImage(tempCanvas,-140,-140)
C'est bon j'ai réussi, voici la photo du résultat :
L'adresse du code source est la suivante :
https://github.com/Linefate/Dynamic-effect-of-canvas-ring.git
RésumerCe qui précède est l'introduction de l'éditeur à l'utilisation du canevas html5 pour dessiner des animations en anneau. J'espère que cela vous sera utile. Si vous avez des questions, veuillez me laisser un message et l'éditeur vous répondra à temps. Je tiens également à remercier tout le monde pour votre soutien au site d'arts martiaux VeVb !