Décomposition du cercle SVG en chemins

Publié: 2022-03-10
Résumé rapide ↬ Cet article vous montrera comment transformer des cercles SVG en chemins que vous pouvez utiliser dans des animations et des chemins de texte, ainsi que comment transformer des chemins en cercles. Une fois que vous aurez compris comment tout cela fonctionne, vous pourrez obtenir des effets assez pratiques. Creusons.

Cet article commence par un aveu : j'aime coder manuellement le SVG. Ce n'est pas toujours le cas mais assez souvent cela peut sembler particulier à des personnes qui ne partagent pas ma prédilection. Il y a un bon nombre d'avantages à pouvoir écrire du SVG à la main, comme l'optimisation des SVG d'une manière qu'un outil ne peut pas (transformer un chemin en un chemin ou une forme plus simple), ou en comprenant simplement comment fonctionnent les bibliothèques comme D3 ou Greensock .

Cela dit, j'aimerais examiner de plus près les formes circulaires en SVG et les choses que nous pouvons faire avec elles lorsque nous dépassons un cercle de base. Pourquoi les cercles ? Eh bien, j'adore les cercles. C'est ma forme préférée.

Tout d'abord (j'espère que vous avez déjà vu un cercle de base en SVG), voici un stylo qui en montre un :

Voir le cercle Pen de Bryan Rasmussen.

Voir le cercle Pen de Bryan Rasmussen.

Beaucoup de choses peuvent être faites avec un cercle : il peut être animé et on peut lui appliquer différentes couleurs. Pourtant, il y a deux choses très intéressantes que vous ne pouvez pas faire faire par un cercle dans SVG 1.1 : vous ne pouvez pas faire bouger un autre élément graphique le long du chemin du cercle (en utilisant l'élément animateMotion ) et vous ne pouvez pas façonner un texte le long du chemin d'un cercle (cela ne sera autorisé qu'après la sortie de SVG 2.0).

Plus après saut! Continuez à lire ci-dessous ↓

Transformer notre cercle en chemin

Il existe un petit outil en ligne qui peut vous aider à créer des chemins à partir de cercles (vous pouvez l'essayer ici), mais nous allons tout créer à partir de zéro afin de découvrir ce qui se passe réellement dans les coulisses.

Pour faire un chemin circulaire, nous allons en fait faire deux arcs, c'est-à-dire des demi-cercles qui complètent le cercle dans un chemin. Comme vous l'avez probablement remarqué dans le SVG ci-dessus, les attributs CX , CY et R définissent respectivement où le cercle est dessiné le long des axes X et Y, tandis que R définit le rayon du cercle. Le CX et le CY créent le centre du cercle, de sorte que le cercle est dessiné autour de ce point.

La réplication de ce cercle pourrait ressembler à ceci :

 <path d=" M (CX - R), CY a R,R 0 1,0 (R * 2),0 a R,R 0 1,0 -(R * 2),0 " />

Notez que CX est identique à l'attribut cx du cercle ; il en va de même pour CY et l'attribut cy du cercle, ainsi que R et l'attribut r du cercle. Le petit a est utilisé pour définir un segment d'arc elliptique. Vous pouvez utiliser un Z (ou z ) facultatif pour fermer le chemin.

La lettre minuscule a indique le début d'un arc elliptique dessiné relativement à la position actuelle — ou dans notre cas spécifique :

 <path d=" M 25, 50 a 25,25 0 1,1 50,0 a 25,25 0 1,1 -50,0 " />

Vous pouvez voir la magie se produire dans ce stylo :

Voir le cercle Pen du chemin par Bryan Rasmussen.

Voir le cercle Pen du chemin par Bryan Rasmussen.

Caché sous le chemin se trouve un cercle avec un remplissage rouge. Lorsque vous jouez avec les valeurs du chemin, vous verrez ce cercle tant que le chemin couvre totalement le cercle (le chemin lui-même est un cercle de la même taille), et nous saurons que nous faisons les choses correctement .

Une chose que vous devez également savoir est que tant que vous dessinez des arcs relatifs, vous n'avez pas besoin de répéter la commande a pour chaque arc que vous dessinez. Lorsque vos 7 premières entrées sont terminées pour votre arc, les 7 secondes entrées seront prises pour l'arc suivant.

Vous pouvez essayer cela avec le stylo ci-dessus en supprimant le deuxième a dans le chemin :

 a 25,25 0 1,1 50,0 25,25 0 1,1 -50,0

Cela peut sembler le même, mais je préfère le laisser jusqu'à ce que je sois prêt à terminer un dessin, et cela m'aide aussi à garder une trace de l'endroit où j'en suis.

Comment fonctionne ce chemin

Tout d'abord, nous nous déplaçons vers une coordonnée X,Y absolument positionnée dans l'image. Il ne dessine rien là-bas - il se déplace simplement là-bas. Rappelez-vous que pour un élément de cercle CX , CY désigne le centre du cercle ; mais comme cela se produit dans l'arc elliptique, les véritables CX et CY de l'arc seront calculés à partir des autres propriétés de cet arc.

En d'autres termes, si nous voulons que notre CX soit à 50 et que notre rayon soit à 25 , alors nous devons passer à 50 - 25 (si nous dessinons de gauche à droite, bien sûr). Cela signifie que notre premier arc est tiré de 25 X, 50 Y ce qui donne à notre premier arc 25,25 0 1,0 50,0 .

Décomposons ce que signifie réellement la valeur 25,25 0 1,0 50,0 de notre arc :

  • 25 : Le rayon X relatif de l'arc ;
  • 25 : Le rayon Y relatif de l'arc ;
  • 0 1,0 : Je ne vais pas parler des trois valeurs médianes (rotation, large-arc-flag et les propriétés de balayage) car elles ne sont pas très importantes dans le contexte de l'exemple actuel tant qu'elles sont les mêmes pour les deux arcs ;
  • 50 : La coordonnée X finale (relative) de l'arc ;
  • 0 : La coordonnée Y finale (relative) de l'arc.

Le deuxième arc est un 25,25 0 1,0 -50,0 . Gardez à l'esprit que cet arc commencera à dessiner là où le dernier arc a cessé de dessiner. Bien sûr, les rayons X et Y sont les mêmes ( 25 ), mais la coordonnée X finale est -50 de l'endroit où se trouve l'actuelle.

Évidemment, ce cercle aurait pu être tracé de différentes manières. Ce processus de transformation d'un cercle en chemin est appelé décomposition. Dans la spécification SVG 2, la décomposition d'un cercle se fera avec 4 arcs, cependant, la méthode qu'elle recommande n'est pas encore utilisable, car elle dépend actuellement d'une fonctionnalité nommée chemin de fermeture de segment qui n'a pas encore été spécifiée.

Afin de vous montrer qu'on peut dessiner le cercle de plein de façons, j'ai préparé un petit stylo avec divers exemples :

Voir le Pen all circles de Bryan Rasmussen.

Voir le Pen all circles de Bryan Rasmussen.

Si vous regardez de plus près, vous verrez notre cercle d'origine ainsi que cinq exemples différents de la façon de dessiner des chemins au-dessus de ce cercle. Chaque chemin a un élément enfant desc décrivant l'utilisation des valeurs CX , CY et R pour construire le cercle. Le premier exemple est celui dont nous avons parlé ici tandis que trois autres utilisent des variantes qui devraient être compréhensibles à la lecture du code ; les derniers exemples utilisent quatre arcs semi-circulaires au lieu de deux, reproduisant quelque peu le processus décrit dans la spécification SVG 2 liée ci-dessus.

Les cercles sont superposés à l'aide de l'indexation z naturelle de SVG consistant à placer les éléments qui viennent plus tard dans le balisage au-dessus de ceux qui viennent plus tôt.

Si vous cliquez sur les chemins circulaires dans le stylo, le premier clic imprimera comment le chemin est structuré sur la console et ajoutera une classe à l'élément afin que vous puissiez voir la couleur de trait de la façon dont le cercle est dessiné (vous pouvez voir que le premier cercle est tracé avec un coin de départ à partir du trait). Le deuxième clic supprimera le cercle afin que vous puissiez interagir avec le cercle ci-dessous.

Chaque cercle a une couleur de remplissage différente ; l'élément de cercle réel est jaune et dira "Vous avez cliqué sur le cercle" à la console chaque fois qu'il est cliqué dessus. Vous pouvez aussi, bien sûr, simplement lire le code car les éléments desc sont assez simples.

Passer d'un chemin à un cercle

Je suppose que vous avez remarqué que bien qu'il existe de nombreuses façons différentes de dessiner le cercle, les chemins utilisés semblent toujours assez similaires. Souvent, en particulier dans les sorties SVG d'un programme de dessin, les cercles seront représentés par des chemins. Cela est probablement dû à l'optimisation du code du programme graphique ; une fois que vous avez le code pour dessiner un chemin, vous pouvez dessiner n'importe quoi, alors utilisez-le. Cela peut conduire à des SVG quelque peu gonflés sur lesquels il est difficile de raisonner.

Lecture recommandée : " Conseils pour créer et exporter de meilleurs SVG pour le Web" par Sara Soueidan

Prenons le SVG suivant de Wikipedia comme exemple. Lorsque vous regardez le code de ce fichier, vous verrez qu'il a beaucoup de cruauté d'éditeur une fois que vous l'avez exécuté dans SVGOMG de Jake Archibald ! (sur lequel vous pouvez en savoir plus ici), vous vous retrouverez avec quelque chose comme le fichier suivant qui a été assez optimisé mais les cercles dans le document sont toujours rendus sous forme de chemins :

Voir le Pen Wikipedia Screw Head Clutch Type A par Bryan Rasmussen.

Voir le Pen Wikipedia Screw Head Clutch Type A par Bryan Rasmussen.

Voyons donc si nous pouvons comprendre ce que ces cercles devraient être s'ils étaient de véritables éléments de cercle compte tenu de ce que nous savons sur le fonctionnement des chemins. Le premier chemin dans le document n'est évidemment pas un cercle alors que les deux suivants le sont (affichant uniquement l'attribut d ) :

 M39 20a19 19 0 1 1-38 0 19 19 0 1 1 38 0z
 M25 20a5 5 0 1 1-10 0 5 5 0 1 1 10 0z

Donc, en se souvenant que le second a peut être omis, réécrivons-les pour qu'ils aient un peu plus de sens. (Le premier chemin est le grand cercle.)

 M39 20 a19 19 0 1 1-38 0 a19 19 0 1 1 38 0z

Ces arcs sont alors évidemment les suivants :

 aR R 0 1 1 - (R * 2) 0 aR R 0 1 1 (R * 2) 0

Cela signifie que notre rayon de cercle est de 19 , mais quelles sont nos valeurs CX et CY ? Je pense que notre M39 est en fait CX + R , ce qui signifie que CX est 20 et CY est 20 aussi.

Disons que vous ajoutez un cercle après tous les chemins comme ceci :

 <circle fill="none" stroke-width="1.99975" stroke="red" r="19" cx="20" cy="20" />

Vous verrez que c'est correct et que le cercle rouge couvre exactement le grand cercle. Le deuxième chemin circulaire reformulé ressemble à ceci :

 M25 20 a5 5 0 1 1-10 0 5 5 0 1 1 10 0z

Évidemment, le rayon est de 5 , et je parie que nos valeurs CX et CY sont les mêmes qu'avant : - 20 .

Remarque : Si CX = 20 , alors CX + R = 25 . Le cercle est assis à l'intérieur du plus grand au centre, il devrait donc évidemment avoir les mêmes valeurs CX et CY .

Ajoutez le cercle suivant à la fin des chemins :

 <circle fill="yellow" r="5" cx="20" cy="20" />

Vous pouvez maintenant voir que c'est correct en jetant un œil au stylo suivant :

Voir le Pen Wikipedia Screw Head Clutch Type A_ avec des exemples de cercles par Bryan Rasmussen.

Voir le Pen Wikipedia Screw Head Clutch Type A_ avec des exemples de cercles par Bryan Rasmussen.

Maintenant que nous savons ce que devraient être les cercles, nous pouvons supprimer ces chemins inutiles et créer réellement les cercles - comme vous pouvez le voir ici :

Voir le Pen Wikipedia Screw Head Clutch Type A optimisé par Bryan Rasmussen.

Voir le Pen Wikipedia Screw Head Clutch Type A optimisé par Bryan Rasmussen.

Utilisation de notre chemin circulaire pour l'habillage du texte

Alors maintenant que nous avons nos cercles dans des chemins, nous pouvons envelopper du texte sur ces chemins. Ci-dessous se trouve un stylo avec les mêmes chemins que notre précédent stylo "Tous les cercles", mais avec du texte enveloppé sur le chemin. Chaque fois que vous cliquez sur un chemin, ce chemin sera supprimé et le texte sera enveloppé sur le prochain chemin disponible, comme ceci :

Voir le stylo tous les cercles enveloppés de texte par Bryan Rasmussen.

Voir le stylo tous les cercles enveloppés de texte par Bryan Rasmussen.

En regardant les différents chemins, vous verrez de minuscules différences entre chacun (plus à ce sujet dans un instant), mais il y a d'abord une petite incompatibilité entre navigateurs à voir - particulièrement visible dans le premier chemin :

Développeur Firefox
Chrome
Bord Microsoft

La raison pour laquelle le "S" de départ de "Smashing" se trouve à cet angle amusant dans la solution Firefox est que c'est là que nous avons réellement commencé à tracer notre chemin (en raison de la commande vR que nous avons utilisée). Ceci est plus évident dans la version Chrome où vous pouvez clairement voir le premier coin en forme de tarte de notre cercle que nous avons dessiné :

Chrome ne suit pas tous les coins, c'est donc le résultat lorsque vous modifiez le texte en "Smashing Magazine".

La raison en est que Chrome a un bogue concernant l'héritage de l'attribut textLength déclaré sur l'élément de text parent. Si vous voulez qu'ils se ressemblent tous les deux, placez l'attribut textLength sur l'élément textPath ainsi que sur le texte. Pourquoi? Car il s'avère que Firefox Developer a le même bug si l'attribut textLength n'est pas spécifié sur l'élément text (c'est le cas depuis quelques années maintenant).

Microsoft Edge a un bogue totalement différent ; il ne peut pas gérer les espaces entre le Text et l'élément TextPath enfant. Une fois que vous avez supprimé les espaces et placé l'attribut textLength sur les éléments text et textPath , ils auront tous un aspect relativement identique (avec de petites variations dues aux différences dans les polices par défaut, etc.). Donc, trois bogues différents sur trois navigateurs différents — c'est pourquoi les gens préfèrent souvent travailler avec des bibliothèques !

Le stylet suivant montre comment les problèmes peuvent être résolus :

Voir le Pen all circles wrapped Text fixed TextLength de Bryan Rasmussen.

Voir le Pen all circles wrapped Text fixed TextLength de Bryan Rasmussen.

J'ai également supprimé les différentes couleurs de remplissage car cela permet de voir plus facilement l'habillage du texte. Supprimer les couleurs de remplissage signifie que ma petite fonction pour vous permettre de parcourir les chemins et de voir à quoi ils ressemblent ne fonctionnera pas à moins que j'ajoute un attribut pointer-events="all" , donc je les ai également ajoutés.

Remarque : Vous pouvez en savoir plus sur les raisons de cela dans "Managing SVG Interaction With The Pointer Events Property" expliqué par Tiffany B. Brown.

Nous avons déjà discuté de l'enveloppement du chemin multiarc, alors regardons maintenant les autres. Puisque nous avons un chemin sur lequel nous nous enroulons, le texte se déplacera toujours dans la même direction.

Image Chemin Explication
M CX, CY
a R, R 0 1,0 -(R * 2), 0
a R, R 0 1,0 R * 2, 0
et utilise la fonction translate pour déplacer +R sur l'axe X.
La position de départ de notre textPath (puisque nous ne l'avons spécifié d'aucune façon) est déterminée par notre premier arc de fin -(R * 2) , compte tenu du rayon de l'arc lui-même.
M (CX + R), CY
a R,R 0 1,0 -(R * 2),0
a R,R 0 1,0 (R * 2),0
Même chose que le chemin précédent.
M CX CY
m -R, 0
a R,R 0 1,0 (R * 2),0
a R,R 0 1,0 -(R * 2),0
Puisque nous terminons à (R * 2 ) dans notre premier arc, nous commencerons évidemment à la position opposée. En d'autres termes, celui-ci commence là où nos deux chemins précédents se sont terminés.
M (CX - R), CY
a R,R 0 1, 1 (R * 2),0
a R,R 0 1, 1 -(R * 2),0
Cela commence à la même position que le dernier en raison de (R * 2) , mais il tourne dans le sens des aiguilles d'une montre car nous avons défini la propriété sweep-flag (marquée en jaune) sur 1 .

Nous avons vu comment envelopper du texte sur un seul chemin dans un cercle. Voyons maintenant comment nous pouvons diviser ce chemin en deux chemins et les avantages que vous pouvez en tirer.

Briser nos chemins en plusieurs parties

Il y a beaucoup de choses que vous pouvez faire avec le texte dans votre chemin, c'est-à-dire obtenir des effets stylistiques avec des éléments tspan , définir le décalage du texte ou animer le texte. Fondamentalement, tout ce que vous ferez sera limité par le chemin lui-même. Mais en divisant nos chemins multiarcs en chemins d'arc uniques, nous pouvons jouer avec la direction de notre texte, l'indexation z de différentes parties de notre texte et réaliser des animations plus complexes.

Tout d'abord, nous allons vouloir utiliser une autre image SVG pour montrer certains des effets. J'utiliserai le diamant de l'article sur les événements de pointeur que j'ai mentionné plus tôt. Tout d'abord, montrons à quoi cela ressemblera avec un texte circulaire à chemin unique posé dessus.

Supposons que notre cercle est CX 295, CY 200, R 175 . Maintenant, en suivant la méthode du chemin circulaire, nous voyons maintenant ce qui suit :

 M (CX - R), CY a R,R 0 1,1 (R * 2),0 a R,R 0 1,1 -(R * 2),0 

Voir le Pen SVG Amethyst de Bryan Rasmussen.

Voir le Pen SVG Amethyst de Bryan Rasmussen.

Je ne vais pas parler du chemin ou de la taille du texte, de la couleur de remplissage ou du contour. Nous devrions tous comprendre cela maintenant et être capables de faire en sorte que ce soit ce que nous voulons qu'il soit. Mais en regardant le texte, on voit tout de suite quelques bémols ou limites :

  • Le texte va tous dans une direction;
  • Il pourrait être agréable d'avoir une partie du texte derrière l'améthyste, en particulier là où il est écrit MAGAZINE. Afin d'aligner le « M » et le « E » sur le cercle, le « A » doit être sur le point inférieur latéral de l'améthyste, ce qui semble en quelque sorte déséquilibré d'une autre manière. (J'ai l'impression que le 'A' doit être positionné avec précision et pointer vers le bas à ce point.)

Si nous voulons résoudre ces problèmes, nous devons diviser notre chemin unique en deux. Dans le stylo suivant, j'ai séparé le chemin en deux chemins (et les ai placés dans la zone defs du SVG pour que nos textPath référencés):

Voir le Pen SVG Amethyst two paths de Bryan Rasmussen.

Voir le Pen SVG Amethyst two paths de Bryan Rasmussen.

Encore une fois, en supposant que notre CX est 295, CY 200, R 175 , alors les deux chemins sont au format suivant (pour le chemin semi-circulaire supérieur):

 M (CX - R), CY a R,R 0 1,1 (R * 2),0

Et ce qui suit pour le bas :

 M (CX + R), CY a R,R 0 1,1 -(R * 2),0

Cependant, nous avons toujours du texte circulaire qui se déplace tous dans la même direction. Pour résoudre ce problème pour tout sauf Edge, tout ce que vous avez à faire est d'ajouter l'attribut side="right" à l'élément de text contenant le 'MAGAZINE' textPath .

Faire aller le texte dans une autre direction

Si nous voulons prendre en charge autant de navigateurs que possible, nous devons modifier le chemin et ne pas compter sur l'attribut side qui n'est pas entièrement pris en charge. Ce que nous pouvons faire, c'est copier notre chemin de demi-cercle supérieur, mais changer le balayage de 1 à 0 :

Avant de:

 M 120, 200 a 175,175 0 1, M 120, 200 a 175,175 0 1, 1 350,0 350,0

Après:

 M 120, 200 a 175,175 0 1, M 120, 200 a 175,175 0 1, 0 350,0 350,0

Mais notre texte est maintenant dessiné sur le cercle intérieur défini par le balayage et il ne sera pas aussi beau dans différents navigateurs. Cela signifie que nous allons devoir déplacer la position de notre chemin pour l'aligner avec le 'S' de 'Smashing', agrandir le X de fin du chemin et définir un décalage par rapport au texte. Comme vous pouvez le voir, il y a aussi une petite différence de texte entre Firefox et les autres que nous pouvons améliorer en augmentant l'attribut textLength sur l'élément de text , ainsi qu'en supprimant les espaces du textPath (puisque Firefox pense évidemment que les espaces sont significatifs).

La solution:

Voir le Pen SVG Amethyst deux chemins fixé par Bryan Rasmussen.

Voir le Pen SVG Amethyst deux chemins fixé par Bryan Rasmussen.

Modifier l'index Z d'une partie de notre texte circulaire

Enfin, nous voulons que notre texte passe à la fois devant et derrière l'améthyste. Eh bien, c'est facile. Rappelez-vous que l'indexation z des éléments de SVG est basée sur leur emplacement dans le balisage ? Donc si nous avons deux éléments, l'élément 1 sera dessiné derrière l'élément 2 . Ensuite, tout ce que nous avons à faire est de déplacer un élément de text vers le haut dans notre balisage SVG afin qu'il soit dessiné avant l'améthyste.

Vous pouvez voir le résultat ci-dessous dans lequel des parties du mot 'MAGAZINE' sont masquées par la pointe inférieure de l'améthyste.

Voir le Pen SVG Amethyst two paths z-index de Bryan Rasmussen.

Voir le Pen SVG Amethyst two paths z-index de Bryan Rasmussen.

Si vous regardez le balisage, vous pouvez voir que le demi-cercle inférieur du texte a été déplacé pour être avant le chemin qui dessine l'améthyste.

Animer les parties de notre cercle

Nous avons donc maintenant la possibilité de créer un texte circulaire en contrôlant complètement la directionnalité des parties de notre texte en mettant le texte en deux demi-cercles. Cela peut, bien sûr, aussi être exploité pour faire des animations du texte. Faire des animations SVG multi-navigateurs est vraiment le sujet d'un autre article (ou de beaucoup plus d' articles). Ces exemples ne fonctionneront que dans Chrome et Firefox en raison de l'utilisation de la syntaxe des animations SMIL au lieu des images clés CSS ou d'outils comme Greensock. Mais cela donne un bon indicateur des effets que vous pouvez obtenir en animant le cercle décomposé.

Prenez le stylo suivant :

Voir le Pen SVG Amethyst deux chemins animé par Bryan Rasmussen.

Voir le Pen SVG Amethyst deux chemins animé par Bryan Rasmussen.

Veuillez appuyer sur le bouton 'Rerun' sur le codepen pour voir l'animation en action. Les deux parties de notre texte circulaire commencent à s'animer en même temps, mais ont une durée différente et se terminent donc à des moments différents. Parce que nous animons l'attribut textLength , nous avons mis deux directives d' animate sous chaque texte - une pour l'élément text (pour que Firefox fonctionne) et une pour l'élément textpath (pour que Chrome fonctionne).

Conclusion

Dans cet article, nous avons vu comment transformer un cercle en chemin et inversement, afin de mieux comprendre quand nous devons optimiser un chemin et quand non. Nous avons vu comment transformer le cercle en chemin nous libère pour placer le texte sur le chemin circulaire, mais aussi comment diviser davantage le chemin circulaire en demi-cercles et obtenir un contrôle plus complet sur la directionnalité et l'animation des composants de notre texte circulaire .

Lectures complémentaires sur SmashingMag :

  • Repenser le SVG réactif
  • Animer des fichiers SVG avec SVGator
  • Styliser et animer des SVG avec CSS
  • Gestion de l'interaction SVG avec la propriété Pointer Events