【问题标题】:Safari bug. When trying to animate svg a transformation with a blur filter, safari is very laggySafari 错误。当尝试使用模糊过滤器为 svg 转换设置动画时,safari 非常滞后
【发布时间】: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" width="123%" height="123%" 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" width="100%" height="100%"><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-width="10.764"></circle>
            </g>
        </g>
        
     
<g transform="translate(0,0)" mask="url(#circleClip)">
            <g class="items" transform="translate(36, 36)" filter="url(#motionBlur)">
                <image width="128px" height="128px" xlink:href="https://i.imgur.com/xSpsoPm.png"></image>
                <image width="128px" height="128px" y="-128" xlink:href="https://i.imgur.com/JuG5GrL.png"></image>
                <image width="128px" height="128px" y="-256" xlink:href="https://i.imgur.com/BB2GgC6.png"></image>
                <image width="128px" height="128px" y="-384" xlink:href="https://i.imgur.com/xSpsoPm.png"></image>
                <image width="128px" height="128px" y="-512" xlink:href="https://i.imgur.com/JuG5GrL.png"></image>
                <image width="128px" height="128px" y="-640" xlink:href="https://i.imgur.com/BB2GgC6.png"></image>
                <image width="128px" height="128px" y="-768" xlink:href="https://i.imgur.com/xSpsoPm.png"></image>
                <image width="128px" height="128px" y="-896" xlink:href="https://i.imgur.com/JuG5GrL.png"></image>
                <image width="128px" height="128px" y="-1024" xlink:href="https://i.imgur.com/BB2GgC6.png"></image>
                <image width="128px" height="128px" y="-1152" xlink:href="https://i.imgur.com/xSpsoPm.png"></image>
                <image width="128px" height="128px" y="-1280" xlink:href="https://i.imgur.com/JuG5GrL.png"></image>
                <image width="128px" height="128px" y="-1408" xlink:href="https://i.imgur.com/BB2GgC6.png"></image>
                <image width="128px" height="128px" y="-1536" xlink:href="https://i.imgur.com/xSpsoPm.png"></image>
                <image width="128px" height="128px" y="-1664" xlink:href="https://i.imgur.com/JuG5GrL.png"></image>
                <image width="128px" height="128px" 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);

【问题讨论】:

    标签: javascript svg optimization safari gsap


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 感谢您的回复!我注意到即使没有过滤器,性能也会发生变化,特别是在转换动画上 - 它在 safari 中也滞后
    猜你喜欢
    • 1970-01-01
    • 2020-12-27
    • 2018-07-27
    • 2018-06-05
    • 2015-11-06
    • 2018-03-01
    • 1970-01-01
    • 2012-04-29
    • 2018-01-17
    相关资源
    最近更新 更多