tag - svg transforms
Reste un círculo de otro en SVG (4)
Estoy tratando de encontrar una forma de restar una forma de otra en SVG, creando un agujero en el medio o un mordisco en el costado. Algo así como un trazado de recorte, pero en lugar de mostrar la intersección, quiero mostrar una de las partes fuera de la intersección. Una solución implicaba usar Adobe Flex, pero no sabía cómo implementarla correctamente. Entiendo que hay una forma de hacerlo en Inkscape usando operaciones de ruta booleana, pero quiero mantener los elementos del círculo tal como están en lugar de cambiarlos en elementos de ruta.
<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)" />
Dos respuestas sugieren que (1) use una <máscara> o (2) use el atributo "fill-rule = evenodd" para restar una forma B de una forma A (A A B) .
Ambas respuestas sugeridas resuelven el "agujero en el medio" (B ⊆ A) parte de la pregunta, pero solo el enfoque de la máscara es una solución razonable para la parte "mordida del costado" (B ⊈ A) . El uso de la regla de relleno evenodd significa que las dos formas se tratan por igual, por lo que la parte de la segunda forma que no se cruza con la primera formará parte del resultado. Para morder algo fuera de forma, la forma de "morder" tendría que compartir parte de su borde con la forma mordida. Esto podría ser engorroso para lograr en la práctica.
Un ejemplo: para restar un círculo de otro círculo, debe crear una forma de "mordisco" que es la intersección de dos círculos.
El enfoque de la máscara es mucho más universal.
El truco es usar fill-rule para controlar la visualización de un clip-path. Un ejemplo de rosquilla (cuadrado) sería
<?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>
Utiliza la propiedad de regla de relleno de las formas para eliminar el cuadrado interno; puedes ajustar eso para que se haga con las curvas de bezier para crear un círculo según sea necesario.
Una vez que haya creado el trazado de recorte básico, puede crear un trazado de recorte a partir de él; consulte esta entrada de MDN para obtener información sobre clip-path.
Una máscara es lo que quieres. Para crear una <mask>
, haga las cosas que desea mantener en blanco. Las cosas que quieres ser invisible hacen negro. Los colores intermedios darán como resultado translucidez.
Entonces, el SVG resultante es similar a su pseudo marcado y se ve así:
<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>
Estamos llenando la máscara con un rectángulo blanco, y luego colocamos un círculo negro donde queremos que esté el agujero.
| * | Máscara: utilizada para restar objetos:
| => fill = "white" => Bloques para mostrar
| => fill = "black" => Bloques para eliminar
| => fill = "white" => Coloque el bloque de visualización también dentro de la etiqueta de máscara y rellene el blanco
| => fill = "black" => Coloca el Remove Block dentro de la etiqueta mask y llena el negro
| :: | Ejemplo de usar la máscara para eliminar el centro del rect pequeño de rect largo
<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>
| :: | Ejemplo de usar máscara para eliminar el círculo pequeño central del círculo grande:
<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>