Вычесть один круг из другого в SVG
Я пытаюсь найти способ вычесть одну фигуру из другой в SVG, создавая отверстие в середине или укус из его стороны. Что-то вроде обрезной дорожки, но вместо того, чтобы показывать пересечение, я хочу показать одну из частей вне пересечения. решение задействовано использование Adobe Flex, но я не знал, как его правильно реализовать. Я понимаю, что есть способ сделать это в Inkscape, используя логические операции путь, но я хочу сохранить круг элементы так, как они есть, вместо того, чтобы превращать их в элементы пути.
<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)" />
4 ответов
маска-это то, что вы хотите. Чтобы создать <mask>
делают вещи, которые вы хотите оставить белыми. То, что ты хочешь быть невидимым, становится черным. Цвета между ними приведут к прозрачности.
таким образом, результирующий SVG похож на вашу псевдо-разметку и выглядит так:
<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>
мы заполняем маску белым прямоугольником, а затем ставим черный круг там, где мы хотим, чтобы отверстие было.
фокус в том, чтобы использовать заполнить-правила для управления отображением пути клипа. Пример (квадратного) пончика будет
<?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>
который использует свойство fill-rule фигур для удаления внутреннего квадрата - вы можете настроить это с помощью путей Безье, чтобы создать круг по мере необходимости.
после того, как вы создали основной путь отсечения, вы можете создать путь отсечения из него - см. эта запись MDN для получения информации о clip-path.
/ * / Mask: используется для вычитания объектов:
/ => fill= "white" = > блоки для отображения
/ = > fill= "black" = > блоки для удаления
/ => fill= "white" = > поместите блок отображения также внутри тега маски и заполните белым
|=> fill= "black" = > поместите блок удаления внутри тега маски и заполните черный
|:: / пример использования маски для удаления центральной малой прямой кишки из большой прямой кишки
<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>
|::| пример использования маски для удаления центр малого круга от большого круга:
<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) использовать
оба предложенных ответа решают "дыру в середине"(B ⊆ A) часть вопроса, но только маска подход является разумным решением для части "укус из стороны"(B ⊈ A). С помощью evenodd fill-rule означает две фигуры обрабатываются одинаково, поэтому часть второй фигуры, которая не пересекает первую, будет частью результата. Чтобы откусить что-то от формы, "кусающая" форма должна была бы разделить часть своей границы с укушенной формой. На практике это может оказаться затруднительным.
пример: чтобы вычесть круг из другого круга, вам нужно будет создать" кусающую " форму, которая является пересечением двух кругов.
подход маски много более универсальный.