stroke-dashoffset 造成的高 CPU 与内存占用问题

最近在做一个前端项目(对我终于写前端了),在做动画的时候发现网页很卡,后来发现是 CSS 动画的问题,刚开始开启了 3D 加速,发现然而并没有什么卵用,后来我就开始搜一下这个属性有没有什么过渡方案,就引发了一连串的故事……

stroke-dashoffset 是啥

SVG 中 path 可以构造很多形状,如果要绘制一些动画效果,有两个 stroke 属性非常关键:stroke-dasharraystroke-dashoffset

stroke-dasharray 负责控制实线和虚线,stroke-dashoffset 负责控制每个实线的偏移量。这样组合起来就可以造成一种视觉上的偏移,具体可以阅读第一篇文章中 CodePen 的示例,这不是本文的重点,就不多说了。

关于这点,可以阅读以下两篇文章:

3D 加速怎么开

CSS 的动画无论是 animation 还是 transform 还是 transition 都是不会默认开启 3D 加速的,只有使用到 Z 轴 3D 效果的时候才会启用 3D 加速,因此「使用 Z 轴」就是 3D 加速的要义,我们可以用这种方法强制使用 Z 轴而不影响效果:

.cube {
  -webkit-transform: translateZ(0);
  -moz-transform: translateZ(0);
  -ms-transform: translateZ(0);
  -o-transform: translateZ(0);
  transform: translateZ(0);
  /* Other transform properties here */
}

如果遇到动画闪烁的现象时,可以用以下属性修复这个问题:

.cube {
  -webkit-backface-visibility: hidden;
  -moz-backface-visibility: hidden;
  -ms-backface-visibility: hidden;
  backface-visibility: hidden;

  -webkit-perspective: 1000;
  -moz-perspective: 1000;
  -ms-perspective: 1000;
  perspective: 1000;
  /* Other transform properties here */
}

参考文章:

曲线救国:用 transition 代替 animation

开启了之后,我发现,GPU 倒是用上了(占用率变高了),CPU 和内存使用率没降下来……(╯‵□′)╯︵┻━┻

当时我在想,是不是 animation 或者这个动画不支持 GPU 加速,所以在网上查了一下有没有曲线救国的方法:依靠 transition 确实可以实现,但是这样需要 JavaScript 去切换 className,所以我当时没有直接选择这种方案。(结果万万没想到 Bug 的 workaround 也是 JS 实现的)

真实的故事:stroke-dashoffset 的 Bug

偶然间我搜了一下 stroke-dashoffset CPU 的问题,结果找到了 chromium 的 issue,2012 年的(怎么又是 2012 年的 Bug),实际上在 Firefox 上也能重现,并且至今未修复。它说的就是 stroke-dashoffset 造成的 CPU 满载。

svg动画导致持续占用CPU 中也有类似的问题,是在底层进行修复的,从前端层无法修复,而对于桌面 Web 而言,没有办法打这么底层的补丁。

后来沿着查到了一个一毛一样的问题:How can I animate infinite marker movement down an SVG path without very high CPU usage?

使用了 JS 来代替 CSS 动画:

var lines = d3.selectAll('.flowline');

var offset = 1; 
setInterval(function() {
  lines.style('stroke-dashoffset', offset);
  offset += 1; 
}, 50);  

经过测试,CPU 和内存有效降低了 40% 左右,但止不住 Mac 风扇依旧在狂转,所以放弃了这个动画,因此只做一个记录,诸君根据需求自行取舍。

如果您觉得文章不错,可以通过赞助支持我

标签: 知识, 代码段, 语法

添加新评论