如何使SVG笔画显示背景?



我有一个带有渐变背景和前景图标的SVG。目前,图标只是一个顶部有折线的填充路径,但它可以被分割成多条路径,其中折线将是笔画。然而,我想,而不是有颜色的折线/笔触,让他们显示背景,好像它已经在前景切割了一个洞。由于背景是渐变的(它实际上是一个阴影滤镜),而不是纯色,我不能只使用与背景相同颜色的描边来做到这一点。这就是我想象的结果,如果我可以在多条路径上设置负描边宽度。

作为一个例子,我将使用SVG这实际上是(我的个人资料图片)这是我当前的SVG代码
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" stroke="black" fill="rgb(95,95,95)" viewBox="-30 -30 276 260" width="276" height="260" stroke-width="4">
<defs>
<filter id="shadow" x="-30" y="-30" width="276" height="260">
<feGaussianBlur in="SourceAlpha" out="blurOut" stdDeviation="32"/>
<feBlend in="SourceGraphic" in2="blurOut" mode="normal"/>
</filter>
</defs>
<rect x="-30" y="-30" width="276" height="260" fill="#c41313" stroke="none"/>
<path d="M108 0 L216 54 L216 103 L162 130 L162 152 L135 166 L135 187 L108 200 L82 187 L82 166 L54 152 L54 130 L0 103 L0 54 Z" filter="url(#shadow)"/>
<g fill="none">
<polyline points="82 166, 108 179, 135 166"/>
<polyline points="54 130, 108 157, 162 130"/>
<polyline points="0 54, 108 108, 216 54"/>
<polyline points="49 78.5, 108 49, 167 78.5"/>
<line x1="108" y1="0" x2="108" y2="49"/>
<line x1="108" y1="200" x2="108" y2="108"/>
</g>
</svg>
我想,而不是黑色的轮廓,它是一个空白的图标,像这样。当然,对于这个特殊的图像,我可以手动让每个部分-由黑色轮廓分隔-有自己的路径,没有笔画,重新创建效果,但由于我使用这个图像的方式,我需要笔画宽度是可变的,有特定的路径不允许这样做,除非有一种方法在Javascript或PHP中自动生成这些路径,但我不知道如何实现这一点。我能想到的解决这个问题的唯一方法是找到每个部分的中心,并增加一个灰色轮廓来减少间隙(所以最大间隙的笔画宽度为0,最小间隙的笔画宽度相当于每个部分的半径),但对于我的情况,这仍然是无效的。那么还有什么替代方案呢?

更传统的方法是使用<mask>:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 276 260" width="276" height="260">
<defs>
<mask id="mask" stroke-width="4" stroke="#000">
<g transform="translate(30 30)">
<path id="shapeBG" d="M108 0 L216 54 L216 103 L162 130 L162 152 L135 166 L135 187 L108 200 L82 187 L82 166 L54 152 L54 130 L0 103 L0 54 Z" fill="#fff" />
<g fill="none">
<polyline points="82 166, 108 179, 135 166" />
<polyline points="54 130, 108 157, 162 130" />
<polyline points="0 54, 108 108, 216 54" />
<polyline points="49 78.5, 108 49, 167 78.5" />
<line x1="108" y1="0" x2="108" y2="49" />
<line x1="108" y1="200" x2="108" y2="108" />
</g>
</g>
</mask>
<filter id="shadow" x="0" y="0" width="276" height="260">
<feGaussianBlur in="SourceAlpha" out="blurOut" stdDeviation="32" />
<feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
</filter>
</defs>
<rect id="bg" x="0" y="0" width="100%" height="100%" fill="#c41313" stroke="none" />
<g filter="url(#shadow)">
<rect x="0" y="0" width="100%" height="100%" mask="url(#mask)" fill="rgb(95,95,95)" />
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-30 -30 276 260" width="276" height="260">
<g id="mask" stroke-width="4" stroke="#000">
<path id="shapeBG" d="M108 0 L216 54 L216 103 L162 130 L162 152 L135 166 L135 187 L108 200 L82 187 L82 166 L54 152 L54 130 L0 103 L0 54 Z" fill="#fff" />
<g fill="none">
<polyline points="82 166, 108 179, 135 166" />
<polyline points="54 130, 108 157, 162 130" />
<polyline points="0 54, 108 108, 216 54" />
<polyline points="49 78.5, 108 49, 167 78.5" />
<line x1="108" y1="0" x2="108" y2="49" />
<line x1="108" y1="200" x2="108" y2="108" />
</g>
<text style="font-size:11; font-family:Arial, sans-serif" stroke-width="0" x="0" y="80%" dominant-baseline="middle">Mask: white fills/strokes=opaque; <tspan x="0" dy="12">black fills/strokes=transparent<tspan></text>
</svg>

在右边你可以看到实际的掩模图形:

  • 白色填充/描边将变得不透明
  • 黑色填充/描边将变为透明

<mask>也可以用来获得半透明的笔画,例如通过设置你的笔画颜色为rgb(128,128,128)

关于软件支持,你也可以通过转换到来重新调整你的图形,避免负的viewBox值:有些编辑器在这方面有问题。

使用CSS mix-blend-mode似乎达到了你想要的效果,但不确定如何修复灰色和阴影:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" stroke="black" fill="rgb(95,95,95)" viewBox="-30 -30 276 260" width="276" height="260" stroke-width="4">
<defs>
<filter id="shadow" x="-30" y="-30" width="276" height="260">
<feGaussianBlur in="SourceAlpha" out="blurOut" stdDeviation="32"/>
<feBlend in="SourceGraphic" in2="blurOut" mode="normal"/>
</filter>
</defs>

<rect x="-30" y="-30" width="276" height="260" fill="#c41313" stroke="none"/>
<g stroke="black" style="mix-blend-mode: color-dodge;">
<path d="M108 0 L216 54 L216 103 L162 130 L162 152 L135 166 L135 187 L108 200 L82 187 L82 166 L54 152 L54 130 L0 103 L0 54 Z" filter="url(#shadow)"/>
<g fill="none">
<polyline points="82 166, 108 179, 135 166"/>
<polyline points="54 130, 108 157, 162 130"/>
<polyline points="0 54, 108 108, 216 54"/>
<polyline points="49 78.5, 108 49, 167 78.5"/>
<line x1="108" y1="0" x2="108" y2="49"/>
<line x1="108" y1="200" x2="108" y2="108"/>
</g>
</g>
</svg>

您可以使用绿屏技术在单个过滤器中完成此操作。你让外部和内部的线条纯蓝色和绿色,然后使用ColorMatrix将它们选择到单独的图层中,然后从原始形状中合成/取出它们。使用shape-rendering=crispEdges是很重要的,因为如果你不这样做,会有一些抗锯齿的工件看起来很糟糕。

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-30 -30 276 260" width="276" height="260" stroke-width="4" color-interpolation-filters="sRGB" shape-rendering="crispEdges">
<defs>
<filter id="green-screen" x="-30" y="-30" width="276" height="260">
<feColorMatrix type="matrix" values="0 0 0 0 0  0 2 0 0 -1  0 0 0 0 0  -1 2 -1 0 -1" result="exterior-line"/>
<feColorMatrix in="SourceGraphic" type="matrix" values="0 0 0 0 0   0 0 0 0 0  0 0 2 0 -1  -1 -1 2 0 -1" result="interior-line"/>

<feComposite operator="out" in="SourceGraphic" in2="exterior-line"/>
<feComposite operator="out"  in2="interior-line" result="masked-shape"/>

<feGaussianBlur in="SourceAlpha" out="blurOut" stdDeviation="32"/>
<feComposite operator="over" in="masked-shape"/>
</filter>
</defs>
<rect x="-30" y="-30" width="276" height="260" fill="#c41313"/>
<g filter="url(#green-screen)">
<path d="M108 0 L216 54 L216 103 L162 130 L162 152 L135 166 L135 187 L108 200 L82 187 L82 166 L54 152 L54 130 L0 103 L0 54 Z" fill="rgb(95,95,95)" stroke="rgb(0,255,0)"/>
<g fill="none" stroke="rgb(0,0,255)">
<polyline points="82 166, 108 179, 135 166"/>
<polyline points="54 130, 108 157, 162 130"/>
<polyline points="0 54, 108 108, 216 54"/>
<polyline points="49 78.5, 108 49, 167 78.5"/>
<line x1="108" y1="0" x2="108" y2="49"/>
<line x1="108" y1="200" x2="108" y2="108"/>
</g>
</g>
</svg>

最新更新