前端动画优化方案

参考文章
https://mayandev.top/2020/03/18/interview-question-archive/
https://www.cnblogs.com/onepixel/p/7078617.html

实现动画的方式

  • JavaScript: setTimeout
  • CSS3: transform、animation
  • Html5: canvas、requestAnimationFrame(请求动画帧)

setTimeout动画出现卡顿、抖动的原因

  • setTimeout属于异步任务,需要等主线程空闲才能执行,所以实际执行时间一般比设定的要晚一些 [ JS事件循环 ]
  • 不同设备的屏幕刷新率不同,setTimeout只能设置一个固定的时间间隔,这个时间不一定和屏幕的刷新时间相同

动画优化

  • 优先采用requestAnimationFrame,实现动画帧的并发渲染
  • 做减法,保留主动画性能,去除重要性不大的动画(跑马灯、过程小动画)
  • 大图动画性能消耗非常大,使用transform3D实现GPU加速,动画结束、暂停时,切换回2D,取消加速
  • 按需加载 / 卸载动画
  • 动画帧处理函数简化,减少或去除回流与重绘

requestAnimationFrame

与setTimeout相比,requestAnimationFrame最大的优势:

  • 由系统决定回调函数的执行时间
  • 在屏幕刷新前调用回调函数
  • 保证回调函数在每次屏幕刷新间隔中只执行一次
 let progress = 0
 
 function render() {
	progress += 1;
	
	if (progress < 100) {
		window.requestAnimationFrame(render);
	}
 }

// 第一帧渲染
window.requestAnimationFrame(render);

其他优势

  • CPU节能

    • [×] setTimeout动画,在页面隐藏或最小化后,仍在后台执行动画
    • [√] requestAnimationFrame,页面未激活状态下暂停动画,页面激活后从上次停止的地方继续执行
  • 函数节流

    • [√] 高频事件(onresize等),防止一个刷新间隔内多次执行,没有意义,多次绘制屏幕体现不出来
      requestAnimationFrame保证刷新间隔内,函数只执行一次

优雅降级 - polyfill

requestAnimation存在兼容问题,不同浏览器还需要不同前缀

if(!Date.now)
    Date.now = function() { return new Date().getTime(); };

(function() {
    'use strict';

    var vendors = ['webkit', 'moz'];
    
    for(var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
        var vp = vendors[i];
        window.requestAnimationFrame = window[vp+'RequestAnimationFrame'];
        window.cancelAnimationFrame = (
            window[vp+'CancelAnimationFrame'] || 
            window[vp+'CancelRequestAnimationFrame']
        );
    }
    
    if(
        /iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) ||  // iOS6 is buggy
        !window.requestAnimationFrame ||
        !window.cancelAnimationFrame
    ) {
        var lastTime = 0;
        
        window.requestAnimationFrame = function(callback) {
            var now = Date.now();
            var nextTime = Math.max(lastTime + 16, now);
            return setTimeout(function() {
                callback(lastTime = nextTime)
            },nextTime - now);
        };
        window.cancelAnimationFrame = clearTimeout;
    }
}());

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值