Safari 错误。当尝试使用模糊过滤器为 svg 转换设置动画时,safari 非常滞后

Posted

技术标签:

【中文标题】Safari 错误。当尝试使用模糊过滤器为 svg 转换设置动画时,safari 非常滞后【英文标题】:Safari bug. When trying to animate svg a transformation with a blur filter, safari is very laggy 【发布时间】:2021-09-22 10:55:04 【问题描述】:

我花了很多时间寻找类似的问题,但找不到任何东西。请帮助解决 safari 上的这一差距。

我正在尝试使用模糊滤镜为 svg 中的图片制作动画。这适用于除 safari 之外的所有浏览器。我准备了一个小提琴:https://jsfiddle.net/7pne23Lk/11/

如果有任何帮助或想法,我将很高兴!谢谢

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 250 250">
    <defs>
        <mask id="circleClip" clipPathUnits="userSpaceOnUse">
            <circle cx="100" cy="100" r="80" fill="#fff"></circle>
        </mask>
        
        <circle id="circleA" cx="100" cy="100" r="80"></circle>
        <circle id="circleC" cx="100" cy="100" r="80"></circle>

        <filter id="circleB"   x="-11.5%" y="-11.5%" filterUnits="objectBoundingBox">
            <feGaussianBlur in="SourceAlpha" result="shadowBlurInner1" stdDeviation="4"></feGaussianBlur>
            <feOffset dy="8" in="shadowBlurInner1" result="shadowOffsetInner1"></feOffset>
            <feComposite in="shadowOffsetInner1" in2="SourceAlpha" k2="-1" k3="1" operator="arithmetic" result="shadowInnerInner1"></feComposite>
            <feColorMatrix in="shadowInnerInner1" result="shadowMatrixInner1" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"></feColorMatrix>
            <feGaussianBlur in="SourceAlpha" result="shadowBlurInner2" stdDeviation="4"></feGaussianBlur>
            <feOffset dy="-8" in="shadowBlurInner2" result="shadowOffsetInner2"></feOffset>
            <feComposite in="shadowOffsetInner2" in2="SourceAlpha" k2="-1" k3="1" operator="arithmetic" result="shadowInnerInner2"></feComposite>
            <feColorMatrix in="shadowInnerInner2" result="shadowMatrixInner2" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"></feColorMatrix>
            <feMerge>
                <feMergeNode in="shadowMatrixInner1"></feMergeNode>
                <feMergeNode in="shadowMatrixInner2"></feMergeNode>
            </feMerge>
        </filter>
        <filter id="motionBlur" x="0" y="0"  ><feGaussianBlur in="SourceGraphic" stdDeviation="0,0"></feGaussianBlur></filter>
    </defs>
    
        <g fill="none" fill-rule="evenodd">
            <use fill="#222731" xlink:href="#circleA"></use>
            <g stroke-linejoin="round">
                <use fill="#000" filter="url(#circleB)" xlink:href="#circleC"></use>
                <circle cx="100" cy="100" r="86" stroke="#272d39" stroke-></circle>
            </g>
        </g>
        
     
<g transform="translate(0,0)" mask="url(#circleClip)">
            <g class="items" transform="translate(36, 36)" filter="url(#motionBlur)">
                <image   xlink:href="https://i.imgur.com/xSpsoPm.png"></image>
                <image   y="-128" xlink:href="https://i.imgur.com/JuG5GrL.png"></image>
                <image   y="-256" xlink:href="https://i.imgur.com/BB2GgC6.png"></image>
                <image   y="-384" xlink:href="https://i.imgur.com/xSpsoPm.png"></image>
                <image   y="-512" xlink:href="https://i.imgur.com/JuG5GrL.png"></image>
                <image   y="-640" xlink:href="https://i.imgur.com/BB2GgC6.png"></image>
                <image   y="-768" xlink:href="https://i.imgur.com/xSpsoPm.png"></image>
                <image   y="-896" xlink:href="https://i.imgur.com/JuG5GrL.png"></image>
                <image   y="-1024" xlink:href="https://i.imgur.com/BB2GgC6.png"></image>
                <image   y="-1152" xlink:href="https://i.imgur.com/xSpsoPm.png"></image>
                <image   y="-1280" xlink:href="https://i.imgur.com/JuG5GrL.png"></image>
                <image   y="-1408" xlink:href="https://i.imgur.com/BB2GgC6.png"></image>
                <image   y="-1536" xlink:href="https://i.imgur.com/xSpsoPm.png"></image>
                <image   y="-1664" xlink:href="https://i.imgur.com/JuG5GrL.png"></image>
                <image   y="-1792" xlink:href="https://i.imgur.com/BB2GgC6.png"></image>           
            </g>
        </g>
   
</svg>

<button id="play">
  play
</button>
const blur = document.querySelector("#motionBlur");
const blurFilter = blur.firstElementChild;
const items = document.querySelector('.items');
const button = document.querySelector('#play');


function animate() 
  gsap.set(items,  y: 140 );

  const tl = gsap.timeline();

  tl.to(items, duration: 0.5, y: 1195, onUpdate: () => 
    const progress = tl.progress() * 20;
    blurFilter.setAttribute('stdDeviation', `0,$20 - progress`);

    if (tl.progress() >= 0.9) 
      blurFilter.setAttribute('stdDeviation', `0,0`);
    

  )


button.addEventListener("click", animate, false);

【问题讨论】:

【参考方案1】:

Safari 中的 SVG 滤镜动画性能可能很差 - 所以这并不完全出乎意料。我有几个建议。

    将 color-interpolation-filters="sRGB" 添加到您的 svg 元素

    神奇的建议 - 将您的 SVG 分解为两个独立的 SVG 元素 - 其中一个包含非动画过滤器和内容,另一个包含动画过滤器和内容。我不知道这是否可行,但值得一试。您的第一个过滤器非常复杂,如果 Safari 在您动画的每一个刻度上都重新渲染它(即使它不是动画的) - 它可能会影响您的性能。

    另一种方法是使用“使用”元素预先渲染 20 个以不同模糊级别绘制的图像副本,然后使用不透明动画逐步显示和隐藏每个图层。不透明动画通常很快——即使在 Safari 上也是如此,因此这可能是一种可行的技巧,尽管它会使您的标记更加复杂。 (还有另一个提示 - 不要将不透明度从 0 设置为 1 - 从 0.01 或 0.04 设置为 1 - webkit 有时会通过不呈现 0 不透明度内容来进行优化 - 在这种情况下,您正试图强制它这样做。)

【讨论】:

感谢您的回复!我注意到即使没有过滤器,性能也会发生变化,特别是在转换动画上 - 它在 safari 中也滞后

以上是关于Safari 错误。当尝试使用模糊过滤器为 svg 转换设置动画时,safari 非常滞后的主要内容,如果未能解决你的问题,请参考以下文章

如何使用SVG滤镜创建模糊的标签背景?

过滤器:mozilla firefox <svg> 的模糊不工作

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

CSS 中 SVG 过滤器的奇怪错误

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

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