SVG 阴影被切断
Posted
技术标签:
【中文标题】SVG 阴影被切断【英文标题】:SVG shadow cut off 【发布时间】:2013-07-26 20:37:28 【问题描述】:我正在使用的 SVG 通过feGaussianBlur
过滤器有一个投影。
阴影本身显示正常,但在顶部和底部边缘被截断。
像这样:
有问题的 SVG 是:
<?xml version="1.0" standalone="no" ?>
<!DOCTYPE svg
PUBLIC '-//W3C//DTD SVG 1.1//EN'
'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'>
<svg version="1.1" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs/>
<filter id="SVGID_0">
<feGaussianBlur in="SourceGraphic" stdDeviation="6.6"/>
<feOffset dx="0" dy="0"/>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<path d="M 0 83 Q 0 83 0 83 Q 0 83 6 79.5 Q 12 76 17 71 Q 22 66 30.5 57.5 Q 39 49 54 36 Q 69 23 82.5 16.5 Q 96 10 120 4.5 Q 144 -1 170.5 0 Q 197 1 218 16.5 Q 239 32 253.5 51 Q 268 70 278 83.5 Q 288 97 299 110 Q 310 123 320 129.5 Q 330 136 338 136.5 Q 346 137 355 129.5 L 364 122" stroke-linecap="round" style="stroke: #005e7a; stroke-width: 30; fill: none; filter: url(#SVGID_0);" transform="translate(50 50)" />
</svg>
Chrome (30)、Firefox (25) 和 Opera (12) 中的裁剪似乎始终如一。
我可以看到这不是视图框限制,因为它设置为 600x700。
我还可以在 devtools 检查器中看到 <path>
元素的边界框,这几乎就是切断阴影的原因:
如果是这样的话:
-
为什么阴影只垂直切断而不是水平切断?
如何解决它,以免它被这样剪裁?
如果不是边界框,是什么原因造成的以及如何避免这种剪切?
【问题讨论】:
【参考方案1】:您需要增加过滤区域的大小。
<filter id="SVGID_0" y="-40%" >
工作得很好。过滤器区域的默认默认设置是:x="-10%" y="-10%" - 大的模糊通常会被剪掉。 (你的阴影没有被水平裁剪,因为你的宽度大约是你的高度的 2.5 倍 - 所以 10% 会导致更宽的水平过滤区域)。此外,y 过滤器区域似乎被计算为好像路径具有零像素笔划,因此它忽略了笔划宽度。 (不同的浏览器有不同的行为,他们是否将笔画视为边界框的一部分以用于过滤器区域计算。)
(更新:从 cmets 上移观察值)
请注意,如果您的特定形状是零宽度或零高度(例如水平或垂直线),那么您必须在过滤器声明中指定filterUnits="userSpaceOnUse"
并在 userSpaceUnits(通常是像素)中明确指定一个过滤区域(x,y,width 高度),以创建足够的空间来显示阴影。
【讨论】:
啊,很有趣。不知道过滤器的区域,但现在可以在规范中查看。 如果您事先不知道阴影的大小,您将如何设置滤镜的 y 属性和高度属性?您是否只需要即时设置它,还是可以说“我希望我的影子永远不会被切断,无论它有多大?” 你可以创建一个非常大的默认阴影区域,但这也会占用内存。非常大的阴影也非常消耗性能,因此最好避免使用它们。 您可以使用filterUnits="userSpaceOnUse"
将阴影区域设置为viewBox 的大小,这实际上将其绝对定位(在SVG 的画布上)。然后可以指定像素位置和大小<filter id="drop_shadow" x="0" y="0" height="*svg-viewbox-height*" width="*svg-viewbox-width*" filterUnits="userSpaceOnUse">
Nilloc - 你想让那些 x 和 y 为负数,这样它们就不会剪裁模糊的左边缘和上边缘。 filterUnits 改变了单位系统,但不改变坐标的 0,0 - 它始终位于边界框的左上角(尽管光源的处理方式不同)【参考方案2】:
如果你在 html 中使用它,你可以简单地使用 CSS 属性来解决这个问题。
svg
overflow: visible !important;
我没有检查过其他浏览器,但是chrome在svg标签上默认有overflow: hidden
。
有点晚了,但希望对你有帮助。
【讨论】:
有人投了反对票;是否有充分的一般理由不应用此属性? 谢谢,我觉得很有用。 我投了反对票。有时 SVG viewBox 会切断阴影,但这个问题不是这样。使用 OP 的代码尝试您的解决方案 - 它不起作用。 此外,« !important » 语句通常不受欢迎(有理由)。尽管该子句的存在有充分的理由,但它几乎从未用于它。而且“我不得不使用它,因为我无法访问原始代码”也不是一个好的理由。 :-) @Eren555 我想您可以将 SVG 包装在一个 div 中,使该 div 的高度大于 SVG,以便在底部有额外的空间。然后让svg的溢出可见,div的溢出不可见。我还没有检查解决方案,但我认为应该可以解决问题【参考方案3】:为filter
shadow svg 标签添加属性:
filterUnits="userSpaceOnUse"
最终输出:
<filter id="dropshadow" filterUnits="userSpaceOnUse" >
这使得阴影在其容器之外绝对定位和可见。
【讨论】:
祝杰克好运!以上是关于SVG 阴影被切断的主要内容,如果未能解决你的问题,请参考以下文章