85 votes

Dessiner un cercle creux en SVG

Je ne sais pas comment aborder le dessin d'un cercle creux en SVG.

J'aimerais que la forme d'un anneau soit remplie d'une couleur et que son contour soit noir.

La façon dont j'ai pensé à le faire était d'avoir 2 cercles, l'un avec un plus petit rayon que l'autre. Le problème est que lorsque je les remplis, comment faire en sorte que le plus petit cercle prenne la même couleur de remplissage que le cercle sur lequel il se trouve ?

125voto

Robert Longson Points 24231

Il suffit d'utiliser fill="none" et ensuite seulement le stroke (contour) sera dessiné.

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
   <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="none" />
</svg> 

Ou ceci si vous voulez deux couleurs :

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
   <circle cx="100" cy="50" r="40" stroke="black" stroke-width="3" fill="none" />
   <circle cx="100" cy="50" r="39" stroke="red" stroke-width="2" fill="none" />
</svg>

9 votes

Le problème est que cela ne me permet pas de conserver le contour noir. Je voudrais une forme d'anneau avec un contour noir.

2 votes

@luketorjussen : pour moi, c'est juste un contour noir. Si vous voulez une couleur de remplissage différente, il suffit de changer l'attribut de remplissage.

0 votes

@rampiom : Je veux avoir un anneau d'une couleur donnée, le tout avec un contour noir.

20voto

Philip Points 1280

La réponse de MDragon00 fonctionne, mais les cercles intérieur et extérieur ne sont pas parfaitement alignés (par exemple, centrés).

J'ai un peu modifié son approche, en utilisant 4 arcs de demi-cercle (2 extérieurs et 2 intérieurs dans le sens inverse) pour obtenir l'alignement exact.

<svg width="100" height="100">
  <path d="M 50 10 A 40 40 0 1 0 50 90 A 40 40 0 1 0 50 10 Z M 50 30 A 20 20 0 1 1 50 70 A 20 20 0 1 1 50 30 Z" fill="#0000dd" stroke="#00aaff" stroke-width="3" />
</svg>

<!--

Using this path definition as d:

M centerX (centerY-outerRadius)
A outerRadius outerRadius 0 1 0 centerX (centerY+outerRadius)
A outerRadius outerRadius 0 1 0 centerX (centerY-outerRadius)
Z
M centerX (centerY-innerRadius)
A innerRadius innerRadius 0 1 1 centerX (centerY+innerRadius)
A innerRadius innerRadius 0 1 1 centerX (centerY-innerRadius)
Z

-->

18voto

Jawad Points 1727

Grâce à Chasbeen, j'ai trouvé comment faire un véritable anneau/donut en SVG. Notez que le cercle extérieur n'est pas fermé, ce qui est seulement apparent quand vous utilisez un trait. Très utile lorsque vous avez de nombreux anneaux concentriques, surtout s'ils sont interactifs (par exemple, avec des commandes de survol CSS).

Pour la commande de dessin...

M cx, cy // Move to center of ring
m 0, -outerRadius // Move to top of ring
a outerRadius, outerRadius, 0, 1, 0, 1, 0 // Draw outer arc, but don't close it
Z // default fill-rule:even-odd will help create the empty innards
m 0 outerRadius-innerRadius // Move to top point of inner radius
a innerRadius, innerRadius, 0, 1, 1, -1, 0 // Draw inner arc, but don't close it
Z // Close the inner ring. Actually will still work without, but inner ring will have one unit missing in stroke       

JSFiddle - Contient plusieurs anneaux et CSS pour simuler l'interactivité. Notez l'inconvénient qu'il manque un seul pixel au point de départ (en haut), qui n'est présent que si vous ajoutez un trait.

Edit : J'ai trouvé ceci Réponse SO (et encore mieux, cette réponse ) qui décrit comment obtenir les entrailles vides en général

1 votes

Cette réponse est brillante ! Et tellement importante si vous voulez que la partie intérieure de l'anneau ne réponde pas aux événements de survol !

0 votes

Pour être vraiment précis, après le deuxième m La valeur x est 1 et non 0 : m 1, outerRadius-innerRadius

7voto

GHC Points 2270

Vous pouvez le faire conformément à la spécification SVG en utilisant un chemin à deux composantes et fill-rule="evenodd". Les deux composants sont des arcs semi-circulaires qui se rejoignent pour former un cercle (dans l'attribut "d" ci-dessous, ils se terminent tous par un "z"). La zone située à l'intérieur du cercle ne fait pas partie de la forme, d'où une bonne interactivité.

Pour décoder un peu le texte ci-dessous, le "340 260" est le milieu supérieur du cercle extérieur, le "290 290" est le rayon du cercle extérieur (deux fois), le "340 840" est le milieu inférieur du cercle extérieur, le "340 492" est le milieu supérieur du cercle intérieur, le "58 58" est le rayon du cercle intérieur (deux fois) et le "340 608" est le milieu inférieur du cercle intérieur.

<svg viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg">
    <path fill-rule="evenodd" d="M340 260A290 290 0 0 1 340 840A290 290 0 0 1 340 260zM340 492A58 58 0 0 1 340 608A58 58 0 0 1 340 492z" stroke-width="4" stroke="rgb(0,0,0)" fill="rgb(0,0,255)">
        <title>This will only display on the donut</title>
    </path>
</svg>

1voto

Chasbeen Points 1275

C'est la forme classique du beignet Je ne sais pas si vous essayez d'atteindre cet objectif avec un SVG standard ou un JavaScript qui produit du SVG. L'objectif peut être atteint en incluant une commande relative "moveto" dans une définition de chemin unique.

Et cliquez sur "trous de beignets" sur le côté droit des exemples interactifs. Vous pouvez au moins voir la définition du chemin qui a donné naissance au beignet rouge.

0 votes

Merci, ça m'a aidé. En fait, c'était difficile à comprendre exactement (et le trait extérieur est à environ 1 unité d'être fermé, ce qui est correct selon moi), mais j'ai trouvé la syntaxe pour créer un anneau avec un point central arbitraire et des rayons extérieur et intérieur à partir de ceci

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X