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

10
我想通过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 height="150" width="150">
    <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的红色圆形元素上应用一个阴影效果,但并没有效果。

搜索后,我没有找到关于此的具体信息,其他与SVG相关的问题中只有少数评论简单地表示它不适用于单个SVG元素,但没有详细解释。

更新

正如@azeós在评论中指出的那样,在Firefox(v. 43.0.2)中可以正确渲染,因此这是Chrome特定的问题。是否有办法在不像评论中建议的那样动手调整SVG代码的情况下实现跨浏览器兼容性呢?


只是好奇,为什么不使用SVG滤镜来创建阴影? - Harry
像Harry建议的那样,我认为你在SVG代码中实现投影效果的最佳选项是使用滤镜。http://www.w3schools.com/svg/svg_feoffset.asp - Fraser Crosbie
是的,我应该在问题中指定,由于工作流程,我想避免与SVG代码搞乱。这真的是唯一可行的选择吗? - Gruber
1
我看到了这个问题的阴影...你用的是哪个浏览器?Waterfox 40.1.0?https://dev59.com/r2025IYBdhLWcg3wT0Hq#13624469 - azeós
哦,不错,我正在使用Chrome,我也可以在Firefox上看到阴影。我猜这是Chrome的问题。Chrome有什么具体问题?我已经更新了问题。 - Gruber
3个回答

25

2020-04更新:因为我找不到关于这个问题的任何信息,所以我进行了一些实验,并且结果非常不一致。

简短结论:SVG阴影效果非常不一致,但HTML阴影效果可靠(除了IE11)。如果您想要SVG阴影效果,您需要使用一个polyfill或者直接在SVG本身中添加阴影效果。

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

Chrome 81 + Canary 83:

在SVG对象的阴影效果上,Chrome和Edge Canary都不能正确地识别filter-webkit-filter,但对于简单的div可以正常工作。

enter image description here

Firefox 75 + Firefox 53 (pre-quantum):

无论是SVG还是HTML对象,Firefox表现得相当不错。

enter image description here

Safari 13+

早期版本的Safari曾经有阴影效果,但又将其去除。

enter image description here

Safari 10.1 - 11

Safari在10.1(和可能的10.0)系列中解决了这个问题。

这里输入图片描述信息

Safari 9.x

SVG CSS 阴影不显示,而 div 的阴影因某种原因具有较少的透明度。

这里输入图片描述信息

Edge (Chromium 版本)

没有 SVG 阴影,但 HTML 阴影工作正常。

这里输入图片描述信息

IE11

没有任何效果。

这里输入图片描述信息


有趣的研究,谢谢!我现在无法测试polyfill,你能确认它在Chrome上也能正常工作吗? - Gruber
我还没有尝试过这个 polyfill,因为今天在我的时区已经结束了,我明天会去尝试。如果你尝试了,请告诉我。 - serraosays

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 height="150" width="150" 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技巧,就我所见,它起作用了!非常棒!我可以问一下那个矩阵网格的文档在哪里吗? :) - Gruber
1
规范在这里:https://www.w3.org/TR/SVG11/filters.html#feColorMatrixElement。演示玩具在这里:https://beta.observablehq.com/@gitmullany/filter-effects-using-svg-color-matrices。该矩阵将所有红色值的不透明度加倍,将其他所有颜色的不透明度清零,然后减去1。其效果是只保留rgb(255,0,0)的物体不透明度为100%。 - Michael Mullany
哇塞,SVG 真是神器啊!我不知道它可以做这么多事情,看来我需要好好更新一下这方面的知识了 x) 谢谢! - Gruber

1
这个 CodePen 中,我为动态生成的pathtext添加了不同的投影效果这里我发现了一个跨浏览器的解决方案,你可以将其应用于一个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)); }

第一个 CodePen中,我评论了另一种不使用的替代方法,而是使用在<defs></defs>中定义的#numbers_dropshadows_filter#strokes_dropshadows_filter
干杯

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接