web-dev-qa-db-fra.com

Soustrayez un cercle d'un autre en SVG

J'essaie de trouver un moyen de soustraire une forme d'une autre en SVG, en créant un trou au milieu ou une morsure sur le côté. Un peu comme un tracé de détourage, mais au lieu de montrer l'intersection, je veux montrer l'une des parties en dehors de l'intersection. ne solution impliquait l'utilisation d'Adobe Flex, mais je ne savais pas comment l'implémenter correctement. Je comprends qu'il existe un moyen de le faire dans Inkscape en utilisant des opérations de chemin booléen, mais je veux garder les éléments du cercle tels qu'ils sont au lieu de les changer en éléments de chemin.

<defs>
    <subtractPath id="hole">
        <circle r="50" cx="100" cy="100" />
    </subtractPath>
</defs>
<circle id="donut" r="100" cx="100" cy="100" subtract-path="url(#hole)" />
33
Iktys

Un masque est ce que vous voulez. Créer un <mask>, faites des choses que vous voulez garder blanches. Les choses que vous voulez être invisibles deviennent noires. Les couleurs intermédiaires se traduiront par une translucidité.

Le SVG résultant est donc similaire à votre pseudo-balisage et ressemble à ceci:

<div style="background: #ddf">
  <svg width="200" height="200">
    <defs>
      <mask id="hole">
        <rect width="100%" height="100%" fill="white"/>
        <circle r="50" cx="100" cy="100" fill="black"/>
      </mask>
    </defs>

    <circle id="donut" r="100" cx="100" cy="100" mask="url(#hole)" />

  </svg>
</div>

Nous remplissons le masque avec un rectangle blanc, puis nous mettons un cercle noir où nous voulons que le trou soit.

58
Paul LeBeau

L'astuce consiste à utiliser règle de remplissage pour contrôler l'affichage d'un chemin de clip. Un exemple de beignet (carré) serait

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
  "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">

<svg xmlns="http://www.w3.org/2000/svg"
 width="300" height="300">
<defs>
</defs>
   <g transform="translate(50, 50)">
      <path d="M 0 0 L 0 200 L 200 200 L 200 0 z
               M 50 50 L 50 150 L 150 150 L 150 50 z" fill-rule="evenodd"/>
   </g>
</svg>

Cela utilise la propriété de règle de remplissage des formes pour supprimer le carré intérieur - vous pouvez ajuster cela à faire avec des chemins de Bézier pour créer un cercle selon les besoins.

Une fois que vous avez créé le chemin de détourage de base, vous pouvez en créer un - voir cette entrée MDN pour plus d'informations sur le chemin du clip.

15
Brad Shuttleworth

Deux réponses suggèrent d'utiliser (1) un <mask> ou (2) d'utiliser l'attribut "fill-rule = evenodd" pour soustraire une forme B d'un forme A (A ∖ B).

Les deux réponses suggérées résolvent le "trou au milieu" (B ⊆ A) une partie de la question, mais seule l'approche mask est une solution raisonnable pour la "morsure du côté ”partie (B ⊈ A). L'utilisation de la règle de remplissage evenodd signifie que les deux formes sont traitées de manière égale, de sorte que la partie de la deuxième forme qui ne coupe pas la première fera partie du résultat. Pour mordre quelque chose d'une forme, la forme "mordante" devrait partager une partie de sa bordure avec la forme mordue. Cela peut être difficile à réaliser dans la pratique.

Un exemple: pour soustraire un cercle d'un autre cercle, vous devez créer une forme "mordante" qui est l'intersection de deux cercles.

L'approche par masque est beaucoup plus universelle.

2
Renardo

| * | Masque: utilisé pour soustraire des objets:

| => fill = "white" => Blocs à afficher
| => fill = "black" => Blocs à supprimer

| => fill = "white" => Placer le bloc d'affichage également à l'intérieur de la balise de masque et remplir blanc
.

| :: | Exemple d'utilisation d'un masque pour retirer le petit rect du centre du grand rect

<rect x="20" y="20" width="60" height="60" mask="url(#rmvRct)"/>
<mask id="rmvRct">
    <rect x="20" y="20" width="60" height="60" fill="white"/>
    <rect x="40" y="40" width="20" height="20" fill="black"/>
</mask>

| :: | Exemple d'utilisation d'un masque pour supprimer le petit cercle central du grand cercle:

<circle cx="50" cy="50" r="45" mask="url(#rmvCir)"/>
<mask id="rmvCir">
    <circle cx="50" cy="50" r="45" fill="white"/>
    <circle cx="50" cy="50" r="25" fill="black"/>
</mask>
1
Sujay U N