如何在svg中合并两个形状?

时间:2016-08-28 16:14:29

标签: html svg

我有两种形状:圆形和矩形。想将它们转换成一个数字。在SVG代码中有没有办法做到这一点?

    <svg width="400" height="400">
     <defs>
    <g id="shape" fill="none" stroke="red">
      <rect x="40" y="50" width="40" height="70" />
      <circle cx="50" cy="50" r="50" />
    </g>
  </defs>

  <use xlink:href="#shape" x="50" y="50"  />
  <use xlink:href="#shape" x="200" y="50" />

</svg>

像这样: like this

5 个答案:

答案 0 :(得分:8)

您可以从两个形状中制作<mask><clipPath>,然后使用它来遮罩第三个形状。然后,您可以将投影应用于此。

<svg width="400" height="400">
  <defs>
    <clipPath id="shape">
      <rect x="40" y="50" width="40" height="70" />
      <circle cx="50" cy="50" r="50" />
    </clipPath>
    
    <filter id="shadow">
      <feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
      <feOffset dx="3" dy="3"/>
      <feMerge>
        <feMergeNode/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>

  <g filter="url(#shadow)">
    <rect width="100%" height="100%" fill="red"
          clip-path="url(#shape)"/>
  </g>

</svg>

注意:如果您想知道为什么我们在这里将投影应用于父<g>,那是因为如果我们将其直接应用于<rect>,投影将受制于也夹。

答案 1 :(得分:7)

对于形状周围的群体只有一个阴影是什么错误?

&#13;
&#13;
    <svg width="400" height="400">
  <defs>   
    <filter id="shadow">
      <feGaussianBlur in="SourceAlpha" stdDeviation="3"/>
      <feOffset dx="3" dy="3"/>
      <feMerge>
        <feMergeNode/>
        <feMergeNode in="SourceGraphic"/>
      </feMerge>
    </filter>
  </defs>

  <g filter="url(#shadow)">
      <rect x="40" y="50" width="40" height="70" fill="red"/>
      <circle cx="50" cy="50" r="50" fill="red"/>
  </g>

</svg>
&#13;
&#13;
&#13;

答案 2 :(得分:6)

对于任何寻找如何将两个轮廓形状组合成单个轮廓形状的实际问题的答案的人(而不是在组合形状上放置阴影),这是一个可能的解决方案:

{{1}}

这基本上绘制了从中切出的矩形形状的圆形,并绘制了从中切出的圆形的矩形。当您将这些“穿孔”形状一个放在另一个上面时,您会得到一个看似单一轮廓的形状。

这是SVG实际做的事情:

  1. 它定义了一个名为“canvas”的白色矩形,其大小与SVG相同。
  2. 它定义了两个要组合的形状(“shape1”和“shape2”)。
  3. 它为每个形状定义一个蒙版,将画布(具有白色填充)与形状(默认情况下填充为黑色)组合在一起。请注意,将蒙版应用于形状时,会显示与蒙版白色区域对应的形状部分,而隐藏与黑色部分对应的部分。
  4. 使用应用的其他形状的蒙版绘制每个形状。

答案 3 :(得分:1)

注意:请注意,此解决方案仅提供轮廓的外部部分。

@devuxer 答案的一些变化。可以通过蒙版创建阴影,然后将其应用于黑色形状。在 https://stackoverflow.com/a/50884092/275195 中,使用集合论 (A-B)+(B-A) 创建了两个掩码。然而,在渲染引擎中,像素光栅用于蒙版并应用抗锯齿。这导致 AB 边界处蒙版中的像素为半透明。这可以通过将形状应用于这样的一个面具来避免(基本上是 A+B 减去 A+B 的轮廓):

<svg>
  <!-- Masks seem to be pre-filled with black -->
  <mask id="union">
    <!-- Whatever is white in the mask will be visible of the shape the mask is applied to. -->
    <rect id="A" x="20" y="20" width="50" height="100" stroke="white" fill="none"></rect>
    <!-- Putting a second (, third, ...) shape into the mask will draw the shape over any existing shapes. -->
    <circle id="B" cx="80" cy="60" r="30" stroke="white" fill="none"></circle>
    <!-- Now we delete the inner part of the shapes by drawing black over them. -->
    <rect id="Ainner" x="20" y="20" width="50" height="100" fill="black"></rect>
    <circle id="Binner" cx="80" cy="60" r="30" fill="black"></circle>
  </mask>
  <!-- Applied to a full-screen red rectangle it cuts out the strokes from the mask. -->
  <rect id="A+B" x="0" y="0" width="100%" height="100%" fill="red" mask="url(#union)"></rect>
</svg>

答案 4 :(得分:0)

使用feMorphology过滤器,您可以扩大和缩小对象(MDN)。结合它们,您可以创建一个简单的可重复使用的轮廓:对原件进行放大复印,上漆并将其放在缩小的原件下面。

<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400">
    <defs>
        <filter id="outline">
            <!-- Make a copy of the original,
                grow it by half the stroke width,
                call it outer -->
            <feMorphology
                operator="dilate"
                radius="1"
                result="outer"
            />
            <!-- Make another copy of the original,
                shrink it by half the stroke width,
                call it inner -->
            <feMorphology
                in="SourceGraphic"
                operator="erode"
                radius="1"
                result="inner"
            />
            <!-- Create a color layer... -->
            <feFlood
                flood-color="black"
                flood-opacity="1"
                result="outlineColor"
            />
            <!-- ...and crop it by outer -->
            <feComposite
                operator="in"
                in="outlineColor"
                in2="outer"
                result="coloredOuter"
            />
            <!-- Place the shrunk original over it -->
            <feComposite
                operator="over"
                in="inner"
                in2="coloredOuter"
            />
        </filter>
    </defs>

    <g filter="url(#outline)">
        <rect x="50" y="60" width="40" height="70" fill="red" />
        <circle cx="60" cy="60" r="50" fill="red" />
    </g>
</svg>

如果要使其透明,请用feComposite替换最后一个xor中的operator

<!-- Knock off the shrunk one -->
<feComposite
    operator="xor"
    in="inner"
    in2="coloredOuter"
/>

唯一的警告:曲线上的笔触(即较大的扩张和半径减小)看起来可能会失真,以1px + 1px仍然可以。