SVG通过填充模式减少路径

时间:2019-10-01 21:55:00

标签: svg svg-filters

我尝试绘制一条必须减少路径的形状,如此解决方案Find Parallel or Offset SVG path 我使用过滤器“侵蚀”,但使用图案则无法使用:图案变形。

有没有使用纯SVG / CSS的bezier.js解决方案的方法吗?

这是我的问题的一个样本 我想拥有右侧的形状和左侧的图案。

<!DOCTYPE html>
<html>
    <body>
        <svg>
            <defs>
                <pattern id="circ" x="0" y="0" width="30" height="30" patternUnits="userSpaceOnUse">
                    <rect fill="blue" width="100%" height="100%" />
                    <circle cx="10" cy="10" r="10" fill="green" />
                </pattern>
                <filter id="erode">
                    <feMorphology in="SourceGraphic" operator="erode" radius="10"/>
                </filter>
                <path id="thing" d="M 0,0 H 50 A 35,35 0 1 0 100,50 V 75 C 50,125 0,85 0,85 Z" />
            </defs>
            <use href="#thing" fill="url(#circ)" width="400" height="400" filter="#erode"/>
            <use x="100" href="#thing" filter="url(#erode)" fill="url(#circ)" width="400" height="400" />
        </svg>
    </body>
</html>

2 个答案:

答案 0 :(得分:2)

是的。您可以使用口罩。

svg {
  width: 300px;
}

.purple {
  fill: rebeccapurple;
}

.reduce-me {
  mask: url(#reducer);
}

#reduce-amount {
  stroke-width: 5px;
}
<svg viewBox="0 0 100 100">
  <path class="purple"
        d="M 50,10 Q 100,10, 50,50 Q 0,90, 50,90 
           Q 100,90, 50,50 Q 0,10, 50,10 Z"/>
</svg>


<svg viewBox="0 0 100 100">
  <defs>
    <!-- the shared path that is used by both the purple path and the mask -->
    <path id="shared-path"
          id="p" d="M 50,10 Q 100,10, 50,50 Q 0,90, 50,90
                    Q 100,90, 50,50 Q 0,10, 50,10 Z" />

    <!-- a mask that shrinks the shape by half the stroke-width -->
    <mask id="reducer">
      <use id="reduce-amount" xlink:href="#shared-path"
           fill="white" stroke="black"/>
    </mask>
  </defs>

  <!-- the shape that gets reduced -->
  <use class="purple reduce-me" xlink:href="#shared-path"/>
</svg>

工作原理

如果仅渲染蒙版的外观(在右侧),我们将看到其工作原理。

svg {
  width: 300px;
}

.purple {
  fill: rebeccapurple;
}

.reduce-me {
  mask: url(#reducer);
}

#reduce-amount {
  stroke-width: 10px;
}
<svg viewBox="0 0 100 100">
  <path class="purple"
        d="M 50,10 Q 100,10, 50,50 Q 0,90, 50,90 
           Q 100,90, 50,50 Q 0,10, 50,10 Z"/>
</svg>


<svg viewBox="0 0 100 100">
  <defs>
    <!-- the shared path that is used by both the purple path and the mask -->
    <path id="shared-path"
          id="p" d="M 50,10 Q 100,10, 50,50 Q 0,90, 50,90
                    Q 100,90, 50,50 Q 0,10, 50,10 Z" />
  </defs>

  <use id="reduce-amount" xlink:href="#shared-path"
       fill="white" stroke="black"/>
</svg>

我们使用与面具相同的形状。但是,面罩周围有黑色粗线。面具中的黑色使事物透明。遮罩的其余部分为白色,保持可见状态。

您可以通过更改stroke-width类中的.reduce-amount值来更改形状减少量。

此方法的缺点是: 1.您需要为每个不同的路径形状设置遮罩 2.您不能设置缩小尺寸形状的笔触样式。但是,您可以通过叠加两条具有不同减少量的路径来模拟笔触颜色。

答案 1 :(得分:2)

您可以扩展过滤器以使其起作用。似乎有一个虫子侵蚀了填充图案的形状-它没有正确吸收半径中最小的Alpha通道。但是,如果您从SourceAlpha而不是SourceGraphic开始,然后使用组件传输创建掩码,则它似乎可以工作。

           <svg>
            <defs>
                <pattern id="circ" x="0" y="0" width="30" height="30" patternUnits="userSpaceOnUse">
                    <rect fill="blue" width="100%" height="100%" />
                    <circle cx="10" cy="10" r="10" fill="green" />
                </pattern>
              <filter id="erode3">
<feMorphology in="SourceAlpha" result="eroded"
operator="erode" radius="10"/>
             <feComponentTransfer>
               <feFuncR type="discrete" tableValues="1 0"/>
               <feFuncG type="discrete" tableValues="1 0"/>
               <feFuncB type="discrete" tableValues="1 0"/>
              </feComponentTransfer>
            <feComposite operator ="in" in="SourceGraphic"/>
</filter>

                <path id="thing" d="M 0,0 H 50 A 35,35 0 1 0 100,50 V 75 C 50,125 0,85 0,85 Z" />
            </defs>
            <use href="#thing" fill="url(#circ)" width="400" height="400" filter="url(#erode3)"/>
            <use x="100" href="#thing" filter="url(#erode)" fill="url(#circ)" width="400" height="400" />
        </svg>