You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

SVG中<use>引用<path>的动画在Firefox中无法正常运行

解决Firefox中元素动画失效的雪花动画方案

我太懂这个痛点了——Firefox对独立<use>元素的属性动画确实存在已知兼容性bug,导致你的雪花只有在鼠标移入移出时才偶尔动一下。咱们可以完全不用<use>来做路径引用,直接把雪花路径放到支持x/y属性动画的容器里,比如<svg>元素,这样就能在所有浏览器里流畅动起来了。

修改后的完整代码

<svg xmlns="http://www.w3.org/2000/svg" width="800px" height="150px">
  <defs>
    <!-- 保留原始的雪花路径定义,复用性不变 -->
    <path id="snow-flake-1" fill="#fff" stroke="none" d="M183.3125,43.09375 L183.3125,83.8125 L152.71875,66.125 L137.1875,92.9375 L183.3125,119.65625 L183.3125,179.75 L131.5,149.8125 L131.40625,96.28125 L100.40625,96.34375 L100.46875,131.90625 L65.09375,111.46875 L49.59375,138.3125 L84.875,158.6875 L54.25,176.3125 L69.6875,203.1875 L115.90625,176.59375 L167.90625,206.625 L116.09375,236.53125 L69.6875,209.84375 L54.25,236.71875 L85.0625,254.46875 L49.6875,274.875 L65.1875,301.71875 L100.46875,281.34375 L100.40625,316.6875 L131.40625,316.75 L131.5,263.4375 L183.5,233.4375 L183.5,293.25 L137.1875,320.09375 L152.71875,346.90625 L183.5,329.09375 L183.5,369.9375 L214.5,369.9375 L214.5,329.21875 L245.09375,346.90625 L260.625,320.09375 L214.5,293.375 L214.5,233.28125 L266.3125,263.21875 L266.40625,316.75 L297.40625,316.6875 L297.34375,281.125 L332.71875,301.5625 L348.21875,274.71875 L312.9375,254.34375 L343.5625,236.71875 L328.125,209.84375 L281.9375,236.4375 L229.90625,206.40625 L281.75,176.46875 L328.125,203.1875 L343.5625,176.3125 L312.75,158.5625 L348.125,138.15625 L332.625,111.3125 L297.34375,131.6875 L297.40625,96.34375 L266.40625,96.28125 L266.3125,149.59375 L214.3125,179.59375 L214.3125,119.78125 L260.625,92.9375 L245.09375,66.125 L214.3125,83.9375 L214.3125,43.09375 L183.3125,43.09375 z" transform="scale(0.02) rotate(-15) translate(-202 -202)">
    </path>
    <path id="snow-flake-2" fill="#fff" stroke="none" d="M183.3125,43.09375 L183.3125,83.8125 L152.71875,66.125 L137.1875,92.9375 L183.3125,119.65625 L183.3125,179.75 L131.5,149.8125 L131.40625,96.28125 L100.40625,96.34375 L100.46875,131.90625 L65.09375,111.46875 L49.59375,138.3125 L84.875,158.6875 L54.25,176.3125 L69.6875,203.1875 L115.90625,176.59375 L167.90625,206.625 L116.09375,236.53125 L69.6875,209.84375 L54.25,236.71875 L85.0625,254.46875 L49.6875,274.875 L65.1875,301.71875 L100.46875,281.34375 L100.40625,316.6875 L131.40625,316.75 L131.5,263.4375 L183.5,233.4375 L183.5,293.25 L137.1875,320.09375 L152.71875,346.90625 L183.5,329.09375 L183.5,369.9375 L214.5,369.9375 L214.5,329.21875 L245.09375,346.90625 L260.625,320.09375 L214.5,293.375 L214.5,233.28125 L266.3125,263.21875 L266.40625,316.75 L297.40625,316.6875 L297.34375,281.125 L332.71875,301.5625 L348.21875,274.71875 L312.9375,254.34375 L343.5625,236.71875 L328.125,209.84375 L281.9375,236.4375 L229.90625,206.40625 L281.75,176.46875 L328.125,203.1875 L343.5625,176.3125 L312.75,158.5625 L348.125,138.15625 L332.625,111.3125 L297.34375,131.6875 L297.40625,96.34375 L266.40625,96.28125 L266.3125,149.59375 L214.3125,179.59375 L214.3125,119.78125 L260.625,92.9375 L245.09375,66.125 L214.3125,83.9375 L214.3125,43.09375 L183.3125,43.09375 z" transform="scale(0.027) rotate(15) translate(-202 -202)">
    </path>

    <!-- 核心改动:用<svg>容器替代<use>,直接承载路径和动画 -->
    <pattern id="pt-snow-3" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
      <!-- 第一个雪花:<svg>原生支持x/y属性动画,完美替代<use> -->
      <svg x="5" y="5" width="10" height="10" viewBox="0 0 10 10">
        <use href="#snow-flake-1"/> <!-- 内部引用路径没问题,Firefox对这种场景的动画支持正常 -->
        <animate attributeName="x" dur="4.2357s" repeatCount="indefinite" values="5; 5.7; 5; 3; 6.5; 5"/>
        <animate attributeName="y" dur="3.9s" repeatCount="indefinite" values="5; 3; 5.7; 5; 6.5; 5"/>
      </svg>

      <!-- 第二个雪花:同样用<svg>容器实现独立x/y动画 -->
      <svg x="15" y="15" width="14" height="14" viewBox="0 0 14 14">
        <use href="#snow-flake-2"/>
        <animate attributeName="x" dur="5.0s" repeatCount="indefinite" values="15; 13; 16.5; 15; 15.7; 15"/>
        <animate attributeName="y" dur="3.7357s" repeatCount="indefinite" values="15; 13; 16.5; 15; 15.7; 15"/>
      </svg>
    </pattern>
  </defs>
  <g>
    <rect x="0" width="800" y="0" height="150" fill="#bbb"/>
    <rect x="0" width="800" y="0" height="150" fill="url(#pt-snow-3)" stroke="#888"/>
  </g>
</svg>

关键改动说明

  1. 替换<use><svg>容器<svg>元素原生支持xy属性,且这些属性的动画在Chrome和Firefox中都能稳定运行,彻底避开了Firefox对独立<use>元素的动画bug。
  2. 保留路径复用性:在<svg>容器内部依然可以用<use>引用定义好的雪花路径,这种内部引用的场景不会触发Firefox的bug,同时保留了代码的复用性。
  3. 匹配容器尺寸:根据雪花路径的缩放比例设置<svg>容器的widthheight,确保雪花显示大小和原效果完全一致。

可选替代方案:+transform动画

如果不想用<svg>容器,也可以用<g>元素通过动画transformtranslate值实现移动,代码示例如下:

<g transform="translate(5,5)">
  <use href="#snow-flake-1"/>
  <animate attributeName="transform" dur="4.2357s" repeatCount="indefinite" values="translate(5,5); translate(5.7,5); translate(5,5); translate(3,5); translate(6.5,5); translate(5,5)"/>
  <animate attributeName="transform" dur="3.9s" repeatCount="indefinite" values="translate(5,5); translate(5,3); translate(5,5.7); translate(5,5); translate(5,6.5); translate(5,5)"/>
</g>

不过这种方案需要同时处理x和y的translate值,不如<svg>x/y属性分开动画直观,所以更推荐第一种方案。

内容的提问来源于stack exchange,提问作者Logi

火山引擎 最新活动