简体   繁体   English

如何让 SVG 笔划显示背景?

[英]How can I make a SVG stroke show a background?

I have an SVG with a gradient-like background and a foreground icon.我有一个带有渐变背景和前景图标的 SVG。 Currently, the icon is just one filled path with polylines on top, but it can be instead split into multiple paths where the polyline would be the stroke.目前,该图标只是一个顶部带有多段线的填充路径,但它可以分成多条路径,其中多段线将是笔画。 However, I want to, instead of the polyline/stroke having a colour, have them display the background, as though it has cut a hole in the foreground.但是,我想让它们显示背景,而不是具有颜色的多段线/笔划,就好像它在前景中切了一个洞一样。 Due to the background being a gradient (it's actually a shadow filter) and not a solid colour, I can't just have a stroke with the same colour as the background to do this.由于背景是渐变色(它实际上是阴影滤镜)而不是纯色,我不能只使用与背景颜色相同的笔触来完成此操作。 This is what I imagine the result would be if I could have a negative stroke-width on the multiple paths.这就是我想象的结果,如果我可以在多条路径上使用负笔画宽度。

As an example, I'll use the SVG this is actually for (my profile picture) So, this is my current SVG code例如,我将使用 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>
I would like, instead of the black outline, it to be a gap in the icon, like this . 我希望它不是黑色轮廓,而是图标中的一个缺口,就像这样 Of course, for this particular image, I could just manually make each section- separated by the black outlines- have it's own path without a stroke, re-creating the effect, but due to how I am using this image, I need the stroke-width to be variable, and having specific paths would not allow for this, unless there were a way to automatically generate these paths in Javascript or PHP but I wouldn't know how to implement this. 当然,对于这个特定的图像,我可以手动制作每个部分 - 由黑色轮廓分隔 - 有自己的路径而没有笔触,重新创建效果,但由于我使用此图像的方式,我需要笔触-width 是可变的,并且具有特定路径不允许这样做,除非有一种方法可以在 Javascript 或 PHP 中自动生成这些路径,但我不知道如何实现它。 The only way I can think of getting around this would be to find the centres of each section and increase a grey outline to decrease the gap (so a maximum gap would be a stroke-width of 0 and a minimum gap would have a stroke-width equivalent to the radius of each section), but for my situation this would still not be effective. 我能想到的解决这个问题的唯一方法是找到每个部分的中心并增加灰色轮廓以减小间隙(因此最大间隙将是 stroke-width 为 0,最小间隙将具有 stroke-宽度等于每个部分的半径),但对于我的情况,这仍然无效。 So what alternatives are there? 那么有什么选择呢?

A more conventional approach would be to use a <mask> :更传统的方法是使用<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>

On the right you see the actual mask graphic:在右侧,您可以看到实际的遮罩图形:

  • white fills/strokes will become opaque白色填充/描边将变得不透明
  • black fills/strokes will become transparent黑色填充/描边将变得透明

<mask> could also be used to get semi-transparent strokes eg by setting your stroke color to something like rgb(128,128,128) . <mask>也可用于获得半透明的笔触,例如通过将笔触颜色设置为类似rgb(128,128,128)的颜色。

Regarding software support you might also realign your graphics via a transform to avoid negative viewBox values : some editors have issues with these.关于软件支持,您还可以通过转换重新对齐图形以避免负 viewBox 值:一些编辑器对此有疑问。

UsingCSS mix-blend-mode seems to achieve what you want, not sure how to fix the gray and the shadow yet though:使用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>

You can do this in a single filter with a green-screen technique.您可以使用绿屏技术在单个滤镜中执行此操作。 You make the exterior and interior lines pure blue and green and then use a ColorMatrix to select them into separate layers and then composite/out them from the original shape.您将外部和内部线条设为纯蓝色和绿色,然后使用 ColorMatrix 将它们 select 分成单独的层,然后从原始形状中合成/移除它们。 It's important to use shape-rendering=crispEdges because there are anti-aliasing artifacts that look bad if you don't.使用 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM