如何通过 CSS 将阴影过滤器应用于 SVG 特定元素/路径

Posted

技术标签:

【中文标题】如何通过 CSS 将阴影过滤器应用于 SVG 特定元素/路径【英文标题】:How to apply drop-shadow filter via CSS to SVG specific element/path 【发布时间】:2016-03-31 08:02:16 【问题描述】:

我想通过 CSS 将阴影过滤器应用于内联放置的 SVG 内的特定元素/路径,我不需要需要对整个图形进行阴影处理,只需一个元素在里面。

.shadow 
  fill: red;
  
  -webkit-filter: 
    drop-shadow( 3px 3px 2px rgba(0,0,0,.7) );
          filter: 
    drop-shadow( 3px 3px 2px rgba(0,0,0,.7) );
  <svg  >
    <g>
<path d="M0,0 C-72,132 -72,-26 100,100"></path>
    </g>
    <g class="shadow" >
    <circle class="shadow" cx="100" cy="100" r="20"></circle>
    </g>
  </svg>

正如您在上面看到的,我正在尝试对 SVG 的红色圆圈元素应用投影,但它不起作用。

四处搜索我没有找到任何具体信息,only few comments 在其他 SVG 相关问题中只是说明它不适用于单个 SVG 元素,但没有太多解释。

更新

正如 cmets 中的 @azeós 所指出的,它在 Firefox (v. 43.0.2) 中可以正确呈现,因此这是 Chrome 特有的问题。有没有办法在不摆弄 cmets 中建议的 SVG 代码的情况下制作这个跨浏览器?

【问题讨论】:

只是好奇,为什么不用 SVG 过滤器来创建阴影? 就像 Harry 建议的那样,我认为投影的最佳选择是 svg 代码中的过滤器 w3schools.com/svg/svg_feoffset.asp 是的,应该在问题中指定,我想避免由于工作流程而弄乱 SVG 代码。这真的是唯一可行的选择吗? 我看到了阴影... Waterfox 40.1.0,您使用的是哪个浏览器? ***.com/a/13624469/1095101 哦,太好了,我正在使用 chrome,我也可以在 Firefox 上看到阴影。我想那是 Chrome 的业务。 chrome的具体问题是什么?我已经更新了问题 【参考方案1】:

2020 年 4 月更新:我在这个问题上做了一些实验,因为我也找不到这方面的任何信息,结果也很不一致。

TL;DR:SVG 阴影非常不一致,但 HTML 阴影可以可靠地工作(在 IE11 之外)。如果你想要 SVG 阴影,you're going to have use a polyfill 或者只是做SVG 本身内的阴影。

Codepen 实验: http://codepen.io/staypuftman/pen/GoNoMq

Chrome 81 + 金丝雀 83:

Chrome 和 Edge Canary 都不尊重 filter-webkit-filter 在 SVG 对象投影的上下文中正确,但可以在简单的 div 上工作。

Firefox 75 + Firefox 53(前量子):

对于 SVG 和 html 对象看起来都不错。

Safari 13+

Safari 在早期版本中曾短暂地出现过阴影,但又将其删除了。

Safari 10.1 - 11

Safari 已在 10.1(可能还有 10.0)系列中修复了此问题。

Safari 9.x

SVG CSS 阴影不显示,div 阴影由于某种原因不透明度​​较低

Edge(铬版)

没有 SVG 阴影,但 HTML 效果很好。

IE11

什么都没有。

【讨论】:

有趣的研究,谢谢!我无法在 polyfill 上测试自己,你能确认它也在 chrome 上工作吗? 我还没有尝试过polyfill,我明天必须这样做,因为我在我的时区完成了一天。如果你试一试,请告诉我。【参考方案2】:

您可以通过对要阴影的对象进行颜色选择,创建阴影然后将其合并到原始图形下来选择性地应用阴影。但是你必须通过 CSS 过滤器中的 SVG 过滤器陷门来完成 - 这在 IE 中不起作用。 (所以...... hacky,但可能)

规格在这里:w3.org/TR/SVG11/filters.html#feColorMatrixElement

演示玩具在这里:https://beta.observablehq.com/@gitmullany/filter-effects-using-svg-color-matrices

该矩阵将所有红色值的不透明度加倍,将其他所有值的不透明度归零,然后减去 1。效果是只保留 rgb(255,0,0) 的 100% 不透明度

#mySVG 
   filter: url(#selective-shadow);


.shadow 
  fill: red;
<svg>
 <defs>
   <filter id="selective-shadow">
     <feColorMatrix type="matrix" values="0 0 0 0 0 
                                          0 0 0 0 0
                                          0 0 0 0 0 
                                          2 0 0 0 -1"/>
     <feGaussianBlur stdDeviation="3"/>
     <feOffset dy="2" dx="2"/>
     <feMerge>
       <feMergeNode/>
       <feMergeNode in="SourceGraphic"/>
     </feMerge>         
   </filter>
 </defs>
</svg>



<svg   id="mySVG">
    <g>
<path d="M0,0 C-72,132 -72,-26 100,100"></path>
    </g>
    <g class="shadow" >
    <circle class="shadow" cx="100" cy="100" r="20"></circle>
    </g>
  </svg>

【讨论】:

哦,哇,这是一些高级的 SVG 黑客技术,据我所知,它有效!很不错!请问那个矩阵网格东西的文档在哪里? :) 规格在这里:w3.org/TR/SVG11/filters.html#feColorMatrixElement 演示玩具在这里:beta.observablehq.com/@gitmullany/…。该矩阵将所有红色值的不透明度加倍,将其他所有值的不透明度归零,然后减去 1。效果是只保留 rgb(255,0,0) 的 100% 不透明度 神圣的SVG!!我不知道你可以用 SVG 做这样的事情,该死的猜想我需要对这个主题进行一些更新 x)谢谢!【参考方案3】:

在this CodePen 我添加了不同的 drop-shadows 到动态生成的pathtext。 Here 我找到了一个跨浏览器解决方案,例如,您可以将其应用于class,而不是#robbie img(在第二个链接中):

#robbie img  filter: "progid:DXImageTransform.Microsoft.Dropshadow(OffX=12, OffY=12, Color='#444')";   filter: url(#drop-shadow);   -webkit-filter: drop-shadow(12px 12px 7px rgba(0,0,0,0.5));   filter: drop-shadow(12px 12px 7px rgba(0,0,0,0.5)); 

在first CodePen 中,我评论了另一种不使用 的替代方法,但它使用&lt;defs&gt;&lt;/defs&gt; 中定义的#numbers_dropshadows_filter#strokes_dropshadows_filter

干杯

【讨论】:

以上是关于如何通过 CSS 将阴影过滤器应用于 SVG 特定元素/路径的主要内容,如果未能解决你的问题,请参考以下文章

应用 CSS 过滤器时,内联 SVG 在 iOS 和 Safari 中消失

SVG过滤器插入阴影在Safari中不起作用

如何在 SVG 中制作插入阴影

如何使用 svg 过滤器应用渐变

过渡 SVG 过滤器

为啥过滤器(阴影)导致我的 SVG 在 Safari 中消失?