【问题标题】:SVG filter <feOffset> - possible to set dx and dy in pixel value?SVG 过滤器 <feOffset> - 可以在像素值中设置 dx 和 dy 吗?
【发布时间】:2018-12-18 03:17:05
【问题描述】:

我目前正处于学习和实施 SVG 的阶段,我偶然发现了一个“阴影”问题,我似乎无法将阴影设置为在 px 值中分配。

举个例子:

<filter id="shadow" height="130%" width="130%">
  <feGaussianBlur in="SourceAlpha" stdDeviation="0"></feGaussianBlur>
  <feOffset dx="1" dy="1" result="offsetblur"></feOffset>
  <feFlood flood-color="#fff"></feFlood>
  <feComposite in2="offsetblur" operator="in"></feComposite>
  <feMerge>
  <feMergeNode></feMergeNode>
  <feMergeNode in="SourceGraphic"></feMergeNode>
  </feMerge>
 </filter>

上面给出的阴影比我希望的 css 等价物更大(但显然不是):

filter: drop-shadow(1px 1px 0 #333);

尝试将px 值分配给dxdy 会导致错误,我希望有人能告诉我是否有可能实现我的目标。 “svg + inline filter”和“svg + css filter”的完整示例如下所示:

#css-filter{
-webkit-filter: drop-shadow(1px 1px 0 #333);
filter: drop-shadow(1px 1px 0 #333);
}
hr{
clear:both;
}
svg, p{
width:50%;
float:left;
text-align:center;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="icons-defs" aria-hidden="true" version="1.1" width="200" height="200" viewBox="0 0 200 200">
<defs>
	<filter id="filter" height="130%" width="130%">
  <feGaussianBlur in="SourceAlpha" stdDeviation="0"></feGaussianBlur>
  <feOffset dx="1" dy="1" result="offsetblur"></feOffset>
  <feFlood flood-color="#333"></feFlood>
  <feComposite in2="offsetblur" operator="in"></feComposite>
  <feMerge>
  <feMergeNode></feMergeNode>
  <feMergeNode in="SourceGraphic"></feMergeNode>
  </feMerge>
 </filter>
 </defs>
	<svg filter="url(#filter") viewBox="0 0 16 28" height="150" width="150" fill="yellow">
<path d="M11.5 9c0 0.266-0.234 0.5-0.5 0.5s-0.5-0.234-0.5-0.5c0-1.078-1.672-1.5-2.5-1.5-0.266 0-0.5-0.234-0.5-0.5s0.234-0.5 0.5-0.5c1.453 0 3.5 0.766 3.5 2.5zM14 9c0-3.125-3.172-5-6-5s-6 1.875-6 5c0 1 0.406 2.047 1.062 2.812 0.297 0.344 0.641 0.672 0.953 1.031 1.109 1.328 2.047 2.891 2.203 4.656h3.563c0.156-1.766 1.094-3.328 2.203-4.656 0.313-0.359 0.656-0.688 0.953-1.031 0.656-0.766 1.062-1.813 1.062-2.812zM16 9c0 1.609-0.531 3-1.609 4.188s-2.5 2.859-2.625 4.531c0.453 0.266 0.734 0.766 0.734 1.281 0 0.375-0.141 0.734-0.391 1 0.25 0.266 0.391 0.625 0.391 1 0 0.516-0.266 0.984-0.703 1.266 0.125 0.219 0.203 0.484 0.203 0.734 0 1.016-0.797 1.5-1.703 1.5-0.406 0.906-1.313 1.5-2.297 1.5s-1.891-0.594-2.297-1.5c-0.906 0-1.703-0.484-1.703-1.5 0-0.25 0.078-0.516 0.203-0.734-0.438-0.281-0.703-0.75-0.703-1.266 0-0.375 0.141-0.734 0.391-1-0.25-0.266-0.391-0.625-0.391-1 0-0.516 0.281-1.016 0.734-1.281-0.125-1.672-1.547-3.344-2.625-4.531s-1.609-2.578-1.609-4.188c0-4.25 4.047-7 8-7s8 2.75 8 7z"></path>
</svg>
</svg>
	<svg id="css-filter" viewBox="0 0 16 28" height="150" width="150" fill="red">
<path d="M11.5 9c0 0.266-0.234 0.5-0.5 0.5s-0.5-0.234-0.5-0.5c0-1.078-1.672-1.5-2.5-1.5-0.266 0-0.5-0.234-0.5-0.5s0.234-0.5 0.5-0.5c1.453 0 3.5 0.766 3.5 2.5zM14 9c0-3.125-3.172-5-6-5s-6 1.875-6 5c0 1 0.406 2.047 1.062 2.812 0.297 0.344 0.641 0.672 0.953 1.031 1.109 1.328 2.047 2.891 2.203 4.656h3.563c0.156-1.766 1.094-3.328 2.203-4.656 0.313-0.359 0.656-0.688 0.953-1.031 0.656-0.766 1.062-1.813 1.062-2.812zM16 9c0 1.609-0.531 3-1.609 4.188s-2.5 2.859-2.625 4.531c0.453 0.266 0.734 0.766 0.734 1.281 0 0.375-0.141 0.734-0.391 1 0.25 0.266 0.391 0.625 0.391 1 0 0.516-0.266 0.984-0.703 1.266 0.125 0.219 0.203 0.484 0.203 0.734 0 1.016-0.797 1.5-1.703 1.5-0.406 0.906-1.313 1.5-2.297 1.5s-1.891-0.594-2.297-1.5c-0.906 0-1.703-0.484-1.703-1.5 0-0.25 0.078-0.516 0.203-0.734-0.438-0.281-0.703-0.75-0.703-1.266 0-0.375 0.141-0.734 0.391-1-0.25-0.266-0.391-0.625-0.391-1 0-0.516 0.281-1.016 0.734-1.281-0.125-1.672-1.547-3.344-2.625-4.531s-1.609-2.578-1.609-4.188c0-4.25 4.047-7 8-7s8 2.75 8 7z"></path>
</svg>
<hr>
<p>With inline filter</p><p>With css filter</p>

【问题讨论】:

  • w3.org/TR/SVG/filters.html#feOffsetElement 只是数字,不能提供任何单位。
  • @RobertLongson 感谢您的参考。你知道是否可以重新定义单位以匹配在 css 中以响应方式分配的 px 值?

标签: html css svg svg-filters


【解决方案1】:

这两个过滤器应该是等效的并且行为相同。您的问题是您以两种不同的方式应用过滤器。

在第一种情况下,您将过滤器应用于 SVG 内部 的形状,因此偏移量会受到viewBox 变换的影响。因此它们被放大了。

在第二种情况下,您将过滤器应用于文档级别的最终 SVG。所以 1px 偏移量被视为实际的 1px。

要使它们的行为相同,只需将第一个过滤器移动到最外层的 &lt;svg&gt; 元素,以便以相同的方式应用它。

见下文。

#css-filter {
  -webkit-filter: drop-shadow(1px 1px 0 #333);
  filter: drop-shadow(1px 1px 0 #333);
}

hr {
  clear:both;
}

svg, p {
  width:50%;
  float:left;
  text-align:center;
}
<svg id="icons-defs" width="200" height="200" viewBox="0 0 200 200" filter="url(#filter)">
  <defs>
    <filter id="filter" height="130%" width="130%">
      <feGaussianBlur in="SourceAlpha" stdDeviation="0"></feGaussianBlur>
      <feOffset dx="1" dy="1" result="offsetblur"></feOffset>
      <feFlood flood-color="#333"></feFlood>
      <feComposite in2="offsetblur" operator="in"></feComposite>
      <feMerge>
        <feMergeNode></feMergeNode>
        <feMergeNode in="SourceGraphic"></feMergeNode>
      </feMerge>
    </filter>
  </defs>
  <svg viewBox="0 0 16 28" height="150" width="150" fill="yellow">
    <path d="M11.5 9c0 0.266-0.234 0.5-0.5 0.5s-0.5-0.234-0.5-0.5c0-1.078-1.672-1.5-2.5-1.5-0.266 0-0.5-0.234-0.5-0.5s0.234-0.5 0.5-0.5c1.453 0 3.5 0.766 3.5 2.5zM14 9c0-3.125-3.172-5-6-5s-6 1.875-6 5c0 1 0.406 2.047 1.062 2.812 0.297 0.344 0.641 0.672 0.953 1.031 1.109 1.328 2.047 2.891 2.203 4.656h3.563c0.156-1.766 1.094-3.328 2.203-4.656 0.313-0.359 0.656-0.688 0.953-1.031 0.656-0.766 1.062-1.813 1.062-2.812zM16 9c0 1.609-0.531 3-1.609 4.188s-2.5 2.859-2.625 4.531c0.453 0.266 0.734 0.766 0.734 1.281 0 0.375-0.141 0.734-0.391 1 0.25 0.266 0.391 0.625 0.391 1 0 0.516-0.266 0.984-0.703 1.266 0.125 0.219 0.203 0.484 0.203 0.734 0 1.016-0.797 1.5-1.703 1.5-0.406 0.906-1.313 1.5-2.297 1.5s-1.891-0.594-2.297-1.5c-0.906 0-1.703-0.484-1.703-1.5 0-0.25 0.078-0.516 0.203-0.734-0.438-0.281-0.703-0.75-0.703-1.266 0-0.375 0.141-0.734 0.391-1-0.25-0.266-0.391-0.625-0.391-1 0-0.516 0.281-1.016 0.734-1.281-0.125-1.672-1.547-3.344-2.625-4.531s-1.609-2.578-1.609-4.188c0-4.25 4.047-7 8-7s8 2.75 8 7z"></path>
  </svg>
</svg>

<svg id="css-filter" viewBox="0 0 16 28" height="150" width="150" fill="red">
  <path d="M11.5 9c0 0.266-0.234 0.5-0.5 0.5s-0.5-0.234-0.5-0.5c0-1.078-1.672-1.5-2.5-1.5-0.266 0-0.5-0.234-0.5-0.5s0.234-0.5 0.5-0.5c1.453 0 3.5 0.766 3.5 2.5zM14 9c0-3.125-3.172-5-6-5s-6 1.875-6 5c0 1 0.406 2.047 1.062 2.812 0.297 0.344 0.641 0.672 0.953 1.031 1.109 1.328 2.047 2.891 2.203 4.656h3.563c0.156-1.766 1.094-3.328 2.203-4.656 0.313-0.359 0.656-0.688 0.953-1.031 0.656-0.766 1.062-1.813 1.062-2.812zM16 9c0 1.609-0.531 3-1.609 4.188s-2.5 2.859-2.625 4.531c0.453 0.266 0.734 0.766 0.734 1.281 0 0.375-0.141 0.734-0.391 1 0.25 0.266 0.391 0.625 0.391 1 0 0.516-0.266 0.984-0.703 1.266 0.125 0.219 0.203 0.484 0.203 0.734 0 1.016-0.797 1.5-1.703 1.5-0.406 0.906-1.313 1.5-2.297 1.5s-1.891-0.594-2.297-1.5c-0.906 0-1.703-0.484-1.703-1.5 0-0.25 0.078-0.516 0.203-0.734-0.438-0.281-0.703-0.75-0.703-1.266 0-0.375 0.141-0.734 0.391-1-0.25-0.266-0.391-0.625-0.391-1 0-0.516 0.281-1.016 0.734-1.281-0.125-1.672-1.547-3.344-2.625-4.531s-1.609-2.578-1.609-4.188c0-4.25 4.047-7 8-7s8 2.75 8 7z"></path>
</svg>

<hr>
<p>With inline filter</p><p>With css filter</p>

【讨论】:

  • 我刚开始自己​​撰写答案,由于我的结论或多或少相同,让我在这里补充一下:将过滤器应用于封闭的&lt;span style="filter:url(#filter)"&gt; 会更合适,而不是&lt;svg&gt; 可能再次出现响应问题(如果使用百分比宽度/高度)。 SVG 2 规范中的 How groups are rendered 说明了整体操作顺序,这似乎也适用于内部 &lt;svg&gt;s。
  • 另一个我没能解决的问题是:为什么CSS过滤器符合处理顺序?
  • 感谢保罗的澄清。如果您使用&lt;svg&gt;&lt;use href="..." /&gt;&lt;/svg&gt;,它会如何处理?我猜在这种情况下对 svg 应用过滤器,实际上是引用另一个 svg 和符号,会给出相同的结果并受符号视图框的影响?
  • 如果您将过滤器应用到最外层的&lt;svg&gt; 元素,它不应受到viewBox 转换的影响。如果您将过滤器应用于 SVG 内的元素,它会。
猜你喜欢
  • 2016-05-20
  • 2016-09-23
  • 2021-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多