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

Posted

技术标签:

【中文标题】为啥过滤器(阴影)导致我的 SVG 在 Safari 中消失?【英文标题】:Why is filter(drop-shadow) causing my SVG to disappear in Safari?为什么过滤器(阴影)导致我的 SVG 在 Safari 中消失? 【发布时间】:2016-08-10 20:39:15 【问题描述】:

我正在使用 D3.js 开发应用程序。我有一段时间被转移了,最近又回来了。今天我发现,虽然过去运行良好,但应用程序中的 SVG 地图不再显示在移动版 Safari (ios 9.3.1) 或桌面版 Safari (v9.1 (11601.5.17.1) ) 上。

我提取了 SVG 和单个样式规则并将它们放在 CodePen 上以说明发生了什么。在 Chrome 中,这支笔看起来不错。在 Safari 中,它将完全空白。

https://codepen.io/Kirkman/pen/pyKzeX

如果您在 Safari 中检查 DOM,您会发现路径在那里,并且它们的形状正确。他们只是看起来不可见。在检查器中取消选中样式规则会导致整个地图神奇地出现(显然没有阴影)

样式规则很简单:

svg 
    -webkit-filter: drop-shadow( 2px 2px 4px rgba(0,0,0,.4) );
    filter: drop-shadow( 2px 2px 4px rgba(0,0,0,.4) );

谁能建议为什么这不起作用?是我做错了什么,还是在 Safari 中发生了一些变化?

【问题讨论】:

我在 2016 年向 Apple 提交了一份错误报告,他们说他们在 iOS 11 中修复了这个问题。bugreport.apple.com/web/?problemID=25788891 【参考方案1】:

由于我们使用了<base> 标签,我在 Angular 应用中遇到了同样的问题。

我将它添加到控制器中:

$scope.basePath = window.location.href;

然后在模板中我添加了过滤器的基本路径:

<g ng-attr-filter="url(basePath#filter1_d)">

希望这可以帮助任何使用 Angular 的人。查看 Github 中的此评论以获取更多信息:https://github.com/airbnb/lottie-web/issues/360#issuecomment-320243980

【讨论】:

【参考方案2】:

我在 Safari 中遇到了类似的问题:一旦应用了滤镜效果,线条等 SVG 对象就会消失。相同的代码在 Chrome 和 Firefox 中运行良好。该代码是 Angular 应用程序的一部分。原来问题是由 Angular 使用“base”标签触发的。

Safari 似乎将基本标记应用于嵌入的 SVG 图像中的片段名称,而 Chrome 和 Firefox 则没有。这段代码说明了这个问题:

<html>
 <head>
  <base href="/">
 </head>
 <body>
  <svg>
   <filter filterUnits="userSpaceOnUse" id="glow">
      <feGaussianBlur stdDeviation="1.5"></feGaussianBlur>
   </filter>
   <line x2="99" y2="99" stroke="red" filter="url(#glow)"></line>
   <line y1="99" x2="99" stroke="green" filter="url(/_display/#glow)"></line>
  </svg>
 </body>
</html>

在 Safari 上,只会显示绿线,而 Chrome 和 Mozilla 会显示红线和绿线。

jsfiddle demonstrating the problem

【讨论】:

事实证明这对我来说是破坏 svg 过滤器的原因。您是否为此找到了解决方法?如果能够在 Safari 中同时使用 &lt;base&gt; 和 svg 过滤器,那就太好了。 我知道的唯一解决方法是在过滤器 url 中指定一个绝对路径(如第二个示例所示)。如果过滤器是在 javascript 中创建的,您可以简单地在相对路径前加上 window.location 以使其成为绝对路径。我确实向 Apple 提交了错误报告,但尚未收到回复。【参考方案3】:

当这种情况发生时,我的加载指示器也永远不会停止旋转。此外,当带有设置阴影的样式标签的 SVG 在单独的窗口中打开时,没有阴影。解决方案是使用 SVG 过滤器,并确保复制设置它的元素,以便在调整图像大小时,移动 safari 不会对其进行像素化。例如,如此处所述https://***.com/a/52250105/1267201

【讨论】:

【参考方案4】:

就我而言,我使用的是 SVG 过滤器,因此我无法真正应用 CSS 解决方案。相反,我能够在页面加载后通过 Javascript 应用 CSS 转换来显示 SVG。下面是一个普通 JS 的例子:

setTimeout(function()
 document.getElementById("svg-element").style.display = "block";
,10);

如果您想知道这是否可行,请查看在您调整浏览器大小或使用检查器修改 CSS 样式规则后是否显示 SVG。

【讨论】:

【参考方案5】:

可能有点晚了,但以防万一我会给你我的答案。我对 Safari 也有同样的问题,我发现这似乎是一个 Safari 问题/错误。您可以解决此错误,只需将您的 SVG 标记与另一个 HTML 标记(如 div)包装起来,然后像在示例中所做的那样将阴影过滤器应用于此元素。 在这里,您使用包装器元素修改了示例

https://codepen.io/mauromjg/pen/rLaqWG

<div class="svg-wrapper">
    <svg>...</svg>
</div>

//CSS
.svg-wrapper 
    -webkit-filter: drop-shadow( 2px 2px 4px rgba(0,0,0,.4) );
    filter: drop-shadow( 2px 2px 4px rgba(0,0,0,.4) );

希望有帮助!

【讨论】:

这似乎是完美的解决方法。我会试一试,可能会选择这个作为答案。 这对我来说效果很好。这应该是公认的答案 非常感谢这个解决方案,超级简单,超级干净。应该是公认的答案。 在 iOS 上(在 web 视图或 Safari 本身中——在 11.3 下测试),似乎这种解决方法可能会导致一些间歇性损坏效果和屏幕撕裂,类似于here 所描述的,这不是立即显而易见的.只是提醒一下。 这似乎不是一种解决方法(或至少不再是)。将样式放在 svg 上而不是 codepen 中的包装器上会导致放大时相同的模糊 svg。codepen.io/sarahannnicholson/pen/abvYvEp 与 codepen.io/mauromjg/pen/rLaqWG 在 Safari 移动设备中会导致相同的模糊 svg。【参考方案6】:

浏览器计算方式不同,出于某种原因,Safari 讨厌你。哈哈。

但是,您应该改用 SVG 过滤器。它们更可靠。

SOURCE - w3schools

 <svg  >
  <defs>
    <filter id="f3" x="0" y="0"  >
      <feOffset result="offOut" in="SourceAlpha" dx="20" dy="20" />
      <feGaussianBlur result="blurOut" in="offOut" stdDeviation="10" />
      <feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
    </filter>
  </defs>
  <rect   stroke="green" stroke-
  fill="yellow" filter="url(#f3)" />
</svg> 

希望有帮助!

【讨论】:

经过一些调整,这段代码就可以工作了。但结果不如 CSS 解决方案干净。一个问题是我的一些 SVG 多边形填充了条纹而不是纯色,这导致阴影在这些特定多边形附近看起来更亮。 可以在here 找到类似但稍好一些的技术。仍然有亮度问题,但如果你使用灰色阴影而不是黑色阴影,它就不那么明显了。

以上是关于为啥过滤器(阴影)导致我的 SVG 在 Safari 中消失?的主要内容,如果未能解决你的问题,请参考以下文章

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

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

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

过渡 SVG 过滤器

SVG 阴影被切断

如何在 SVG 中制作插入阴影