SVG在移动端动画卡顿怎么办?
我在用 Vue 做一个移动端的加载动画,用了 SVG 的 animateTransform,但在 iOS Safari 上特别卡,安卓也掉帧。本地开发时 Chrome 看着挺流畅的,一到真机就崩,是不是我写法有问题?
试过加 will-change 和 transform: translateZ(0),都没啥用。下面是我用的代码:
<template>
<svg width="40" height="40" viewBox="0 0 40 40">
<circle cx="20" cy="20" r="10" fill="#333">
<animateTransform
attributeName="transform"
type="rotate"
from="0 20 20"
to="360 20 20"
dur="1s"
repeatCount="indefinite"
/>
</circle>
</svg>
</template>
animateTransform这种)在移动端性能就是不行,W3C文档都建议用CSS动画替代了。推荐的做法是把SVG动画改成CSS transform:
几个关键点:
1. 移除
animateTransform改用CSS动画2. 必须设置
transform-origin,不然旋转中心不对3. 实测加上
will-change: transform在iOS12+有用如果还卡,可以试试用requestAnimationFrame手动控制旋转,虽然代码量多点但性能最好。最近项目里用这个方案,连老款Android机都能跑60fps。
问题根源在于你用的
animateTransform是SVG的SMIL动画,这玩意儿在移动端浏览器上性能支持特别差,尤其是iOS Safari。Chrome桌面端看着流畅是因为它对SMIL做了优化,但真机上的WebView可没这待遇。而且SMIL动画很难触发GPU加速,你加will-change和translateZ(0)基本是白搭,因为那是对CSS生效的,对SMIL不管用。血泪教训:移动端做动画,能不用SMIL就别用,直接换成CSS动画搞定。
给你改好的代码:
改成CSS动画后,
will-change: transform才能真正发挥作用,GPU加速也能正常触发。这样在iOS和安卓上都会流畅很多。还有个小建议,如果这个loading动画比较简单,其实可以直接用纯CSS画个圆,连SVG都不用,性能会更好。SVG在移动端渲染本身就有一定开销,能省则省。