1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > “发得快“踩坑笔记-为什么过渡动画卡顿了?

“发得快“踩坑笔记-为什么过渡动画卡顿了?

时间:2020-06-02 11:14:20

相关推荐

“发得快“踩坑笔记-为什么过渡动画卡顿了?

过渡动画卡顿的解决方案

遇到这个问题的过程

发得快项目在优化时,有个优化是在切换菜单时,让菜单有一个过渡动画,但是在切换到订单时,过渡动画有一个明显的卡顿,要做的就是解决这个卡顿。

代码如下:(代码为demo,公司代码不可泄露)

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>#menu {width: 100px;height: 100px;background: #000;transition: all 2s;color: #fff;}#menu.selected {background: #f00;}</style></head><body><div id="menu">点击触发过渡动画</div><script>let menu = document.getElementById("menu");menu.onclick = function () {// 计时器模拟异步http请求订单setTimeout(() => {kill();}, 500);// 切换选中状态if (menu.classList.value.includes("selected")) {menu.classList.remove("selected");} else {menu.classList.add("selected");}};// while循环卡住js两秒,模拟订单渲染阻塞function kill() {var start = +new Date();while (+new Date() - start < 2000) {}}</script></body></html>

分析问题原因

首先分析卡顿原因,订单界面数据量较大,渲染这个页面需要较长的时间,js执行进程去渲染订单表格时间过长,打断了过度动画的计算,所以出现了卡顿的情况。

浏览器进程与线程分析

浏览器分为几个进程

主进程插件进程GPU进程渲染进程(一个tab页一个进程)

渲染进程又分为几个线程

GUI线程js执行线程dom事件线程计时器线程http线程

关于这个案例,我们需要用到GPU进程,GUI线程与js执行线程

js执行线程主要负责执行js代码,计算HTML 元素的 CSS 样式,绘制位图

GUI线程负责将js绘制好的位图递交给GPU进程,然后GPU进程渲染页面

angular框架在拿到定单数据后做了什么?

拿到定单数据以后,将定单数据赋值给表格的data,angular框架的diff算法计算出改变的虚拟dom节点,并开始绘制,但是50条数据过于庞大,绘制时间过久,造成了卡顿

如何解决

知道了问题是如何发生的,那么就可以思考解决方式,我目前找到了两种方式可以解决这个问题

分散渲染时间

浏览器渲染50条数据时间太久,那么我们就不要一次渲染那么多,只渲染当前能看到的就可以,其他的以后再说,那么渲染的少了,卡顿时间自然也就少了

这种方法没有降低总的渲染时间,只是将一大块时间分散开了,那么在每段时间的间隔中,就可以继续执行过渡动画的渲染

这种思路对应的解决方法是ng-zorro的虚拟滚动,类似懒加载

ng-zorro虚拟滚动示例

使用特定的css

在上网查资料的时候,发现了一个很有意思的demo

demo链接

同样是js阻塞,凭什么transform可以继续动,定位就卡住了呢?

带着这个问题,去查阅资料

发现浏览器对一些css样式有优化处理

深入浏览器理解CSS animations 和 transitions的性能问题

↑这个文章的图片丢失了

图片可以参考这个文章的图片↓

CSS3 动画卡顿解决方案

所以是浏览器对transform,opacity,filter属性有优化

猜测: 浏览器会优化这几个样式是因为,甭管这几个样式怎么变化,都不会影响到其他的dom元素,所以这部分的位图只需要计算一遍就完事了,没有必要重复递交

那么根据这个思路我们改进代码

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>#menu {width: 100px;height: 100px;background: #000;color: #f00;transition: all 2s linear;opacity: 0.2;}#menu.selected {opacity: 1;}</style></head><body><div id="menu">点击开始过渡动画</div><script>let menu = document.getElementById("menu");menu.onclick = function () {setTimeout(() => {kill();}, 500);if (menu.classList.value.includes("selected")) {menu.classList.remove("selected");} else {menu.classList.add("selected");}};function kill() {var start = +new Date();while (+new Date() - start < 2000) {}}</script></body></html>

这样,通过opacity属性,我们也解决了这个卡顿问题

但是这两个方法都有缺点

懒加载方法如果加载的部分需要的时间也比较久的话(比如遇到垃圾电脑),那也会造成卡顿

而更改css属性的方法,由于只有这么几个属性有优化效果,所以并不是所有的动画效果都可以做到的,而且这个方法只解决了卡顿,订单表格加载慢的问题依然存在

所以以后遇到这种过渡动画卡顿的情况,最好把两个方法结合起来

查资料三天,写博客两小时,点个赞噻?

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。