js和css实现动画

js实现动画

  1. 实现方式

    • requestAnimationFrame:将执行动画的每一步传到requestAnimationFrame中,在每次执行完后进行异步回调来连续触发动画效果。
    • setTimeoutsetInterval+css改变(导致页面频繁性重排重绘,消耗性能)
  2. 优点:

    • JavaScript动画控制能力很强, 可以在动画播放过程中对动画进行控制:开始、暂停、回放、终止、取消都是可以做到的。
    • 动画效果比css3动画丰富,有些动画效果,比如曲线运动,冲击闪烁,视差滚动效果,只有JavaScript动画才能完成
    • CSS3有兼容性问题,而JS大多时候没有兼容性问题
  3. 缺点:

    • JavaScript在浏览器的主线程中运行,而主线程中还有其它需要运行的JavaScript脚本、样式计算、布局、绘制任务等,对其干扰导致线程可能出现阻塞,从而造成丢帧的情况。
    • 代码的复杂度高于CSS动画

css实现动画

  1. 实现方式:

    • transition:用来设置样式的属性值是如何从一种状态平滑过渡到另外一种状态,四个参数功能分别为CSS属性的名称、动画时间、速度曲线、动画何时开始
    • transform:2D或者3D的转换,用来设置元素的形状改变
    • animation:逐帧动画,通过设置帧函数,@keyframes
  2. 优点:

    • 浏览器可以对css动画进行优化,浏览器可以对css动画进行优化,其优化原理类似于requestAnimationFrame,会把每一帧的DOM操作都集中起来,在一次重绘和回流中去完成。一般来说频率为每秒60帧。隐藏和不可见的dom不会进行重绘或回流,这样就会更少的使用CPU,GPU和内存使用量。
    • 强制使用硬件加速
    • 代码相对简单,性能调优方向固定
    • 对于帧速不好的浏览器,css3可以做到自动降级,js则需要添加额外的代码。
  3. 缺点:

    • 运行过程控制较弱,无法附加事件绑定回调函数。CSS动画只能暂停,不能在动画中寻找一个特定的时间点,不能在半路反转动画,不能变换时间尺度,不能在特定的位置添加回调函数或是绑定回放事件,无进度报告
    • 代码冗长。想用 CSS 实现稍微复杂一点动画,最后CSS代码都会变得非常笨重。

对比两种方式和各自的适用场景

  • 在需要对动画进行大量控制时,使用 JavaScript

  • 如果您需要手动协调整个场景,可直接使用 requestAnimationFrame

  • 当您为 UI 元素采用较小的独立状态时,使用 CSS

关于requestAnimationFrame的理解

mdn:告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。早期的动画是用setTimeout和setInterval,但是由于受浏览器的事件循环影响,时间不是那么准确(css3带来了transitionanimation ),requestAnimationFrame调用时间则是跟着系统的刷新频率走的,算是一种动画优化方式。
优势:

  • CPU节能:使用SetTinterval 实现的动画,当页面被隐藏或最小化时,SetTinterval 仍然在后台执行动画任务,由于此时页面处于不可见或不可用状态,刷新动画是没有意义的,完全是浪费CPU资源。而RequestAnimationFrame则完全不同,当页面处理未激活的状态下,该页面的屏幕刷新任务也会被系统暂停,因此跟着系统走的RequestAnimationFrame也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了CPU开销。
  • 函数节流:在高频率事件( resize, scroll 等)中,为了防止在一个刷新间隔内发生多次函数执行,RequestAnimationFrame可保证每个刷新间隔内,函数只被执行一次,这样既能保证流畅性,也能更好的节省函数执行的开销,一个刷新间隔内函数执行多次时没有意义的,因为多数显示器每16.7ms刷新一次,多次绘制并不会在屏幕上体现出来。
  • 减少DOM操作:requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。

requestAnimationFrame实现setInterval和setTimeout

function mySetInterval(fn, time) {
  let timer;
  const now = Date.now;
  let startTime = now();
  let endTime = startTime;
  const loop = () => {
    timer = window.requestAnimationFrame(loop);
    endTime = now();
    if (endTime - startTime >= time) {
      startTime = endTime = now();
      fn(timer)
    }
  }
  timer = window.requestAnimationFrame(loop);
  return timer;
}

function mySetTimeout(fn, time) {
  let timer;
  const now = Date.now;
  let startTime = now();
  let endTime = startTime;
  const loop = () => {
    timer = window.requestAnimationFrame(loop);
    endTime = now();
    if (endTime - startTime >= time) {
      startTime = endTime = now();
      fn()
      window.cancelAnimationFrame(timer)
    }
  }
  timer = window.requestAnimationFrame(loop);
  return timer;
}

let a = 0;
mySetInterval((timer) => {
  console.log(a++);
  if (a === 3) {
    window.cancelAnimationFrame(timer)
  }
}, 1000)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值