【问题标题】:Subtract one circle from another in SVG在SVG中从另一个圆中减去一个圆
【发布时间】:2014-04-30 01:04:59
【问题描述】:

我正在尝试找到一种方法,在 SVG 中从另一个形状中减去一个形状,在中间创建一个洞或从它的侧面咬出一个洞。有点像剪切路径,但不是显示交叉点,我想显示交叉点外的一个部分。 One solution 涉及使用 Adob​​e 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)" />

【问题讨论】:

    标签: svg clipping


    【解决方案1】:

    诀窍是使用fill-rule 来控制剪辑路径的显示。一个(方形)甜甜圈的例子是

    <?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>
    

    这使用形状的填充规则属性来删除内部正方形 - 您可以调整它以使用贝塞尔路径来完成,以根据需要创建一个圆。

    创建基本剪辑路径后,您可以从中创建剪辑路径 - 有关剪辑路径的信息,请参阅 this MDN entry

    【讨论】:

      【解决方案2】:

      面具就是你想要的。要创建&lt;mask&gt;,请将您想要保留的内容设为白色。你想要隐形的东西会变黑。中间的颜色会导致半透明。

      因此生成的 SVG 类似于您的伪标记,如下所示:

      <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>

      我们用一个白色矩形填充蒙版,然后在我们想要的孔位置放置一个黑色圆圈。

      【讨论】:

      • 是的,这就是我要找的。我没有想过在面具中使用两个形状。它可以在我的浏览器中运行,但对于我的一生,我无法让它在 Inkscape 中运行。它所做的只是显示大圆圈。会不会是 Inkscape 的错误?
      • 回答我自己的问题,只要一个组包含掩码中的元素,它就可以在 Inkscape 中工作。
      • 有什么办法可以改变颜色吗?比如如果我想让黑色圆圈部分是白色的,而中间的圆圈是半透明的呢?
      • 当然可以。只需设置填充:&lt;circle id="donut" r="100" cx="100" cy="100" mask="url(#hole)" fill="white" /&gt;
      • @Shivam 是的。但是过滤器是在遮罩之前应用的,所以您只需将其包装在一个组中,然后将过滤器应用于该组即可。 jsfiddle.net/86jnkr3L
      【解决方案3】:

      两个答案建议 (1) 使用 或 (2) 使用“fill-rule=evenodd”属性从形状 A 中减去形状 B em> (A ∖ B).

      两个建议的答案都解决了问题的“中间的洞”(B ⊆ A) 部分,但只有 mask 方法是解决“咬伤”的合理解决方案出边”部分(B ⊈ A)。使用 evenodd 填充规则意味着两个形状被平等对待,因此第二个形状不与第一个相交的部分将成为结果的一部分。为了咬出某种形状,“咬”形状必须与被咬形状共享部分边界。这在实践中可能很难实现。

      一个例子:为了从另一个圆中减去一个圆,您必须创建一个“咬合”形状,它是两个圆的交点。

      掩码方法更为普遍。

      【讨论】:

      • 这并不能真正回答原始问题。我害怕作为一个真正需要的答案。如果删除其他答案中的一个或两个,则很难理解您的意思。
      • @RobertLongson:感谢您指出这一点。我不知道可以删除答案。所以我想我的将被删除而无需任何进一步的操作。
      • 为什么不把它转换成可以回答问题的东西呢?
      【解决方案4】:

      |*|蒙版:用于减去对象:

      |=> fill="white" => 要显示的块
      |=> fill="black" => 要删除的块

      |=> fill="white" => 将显示块也放在掩码标签内并填充白色
      |=> fill="black" => 将 Remove Block 放在 mask 标签内并填充黑色

      |::|使用掩码从大矩形中删除中心小矩形的示例

      <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>
      

      【讨论】:

        猜你喜欢
        • 2020-03-02
        • 2011-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多