requestAnimationFrame:循环动画效果

        window.requestAnimationFrame()方法,参考MDN的介绍,其作用是:用于告诉浏览器,希望它执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。这意味着,该方法需要传入一个回调函数作为参数,并且该回调函数会在浏览器下一次重绘之前执行。

如何使用requestAnimationFrame?

        MDN给出了使用的备注信息,

         意思是:如果想要完成一个循环动画的效果,那么,在回调函数的函数体中,必须再次调用window.requestAnimationFrame()方法。

举个栗子:循环动画

        如下代码实现的效果,如上图所示,

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>requestAnimationFrame-例子</title>
  <style>
    *,body,html{
      padding:0;
      margin: 0;
      box-sizing: border-box;
      overflow-x: hidden;
    }
    #animate {
      margin: 1px 0px;
      position: absolute;
      left: 0;
      top: 0;
      width: 100px;
      height: 2px;
      background-color: rgb(0, 164, 230);
    }
  </style>
</head>

<body>
  <div id="animate"></div>
</body>
<script>
  const element = document.getElementById("animate");
  console.log()
  const { clientWidth } = element; //解构:DOM元素的宽度

  //启动滑块动画
  function startAnimate(blockWidth){
    let start = 0;//起始时间
    /**
     * @param {timeStamp} 会被window.requestAnimationFrame()注入调用时间,而实现隐式自增
     * */
    function exectute(timeStamp){
      if(!start) start = timeStamp;
      // console.log(`start=${start}`);
      // console.log(`timeStamp=${timeStamp}`)
      // console.log(timeStamp - start);
      let progress = timeStamp - start; //progress持续增加
      //元素持续右移-最大不超过200px
      element.style.left = Math.min(progress/10,window.innerWidth) +'px';
      if(element.offsetLeft > (window.innerWidth - blockWidth)){
        start = 0;
      }
      //浏览器会自动为window.requestAnimationFrame()的回调函数exectute注入一个double类型的DOMHighResTimeStamp时间值,它表示最近一次浏览器调用execute()函数的时间值
      window.requestAnimationFrame(exectute);//将页面刷新放在下一次重绘之前执行
    }
    exectute(0);
  }
  //启动动画
  startAnimate(clientWidth);

</script>

</html>

循环动画:代码分析

        我们看下这个startAnimate函数的实现,

 

        初看时,可能感觉到很奇怪,因为在调用startAnimate()函数之后,内部的start变量看似是个常量,恒等于0,而且execute()函数的参数也是一个常量0,那么,这个函数体中是如何完成对element滑块的left属性值的修改的呢?

        我们看MDN官方的介绍:

         重点在callback这个参数,在通过window.requestAnimationFrame(execute)的方式执行回调函数时,window.requestAnimationFrame()它会自动向回调函数传入一个参数值——“DOMHighResTimeStamp参数”,它用来表示requestAnimationFrame最近一次执行回调函数execute的毫秒级时间(double类型)——这意味着这个数值是自增的,因此,这个毫秒级的时间就回去主动更新execute()方法的timeStamp参数值。

         那么,我们再来看,滑块是如何回到初始位置呢?关键在于如下的判断逻辑,

        当 element滑块的offsetLeft(等价于left属性去掉px)大于(当前浏览器视口宽度-滑块宽度)时,表示滑块一次循环运动结束,将其置为0。那么,在下一次更新element滑块的left属性时,start被更新,progress结果值为0,element滑块的left=0px,自然就回到初始位置了。

 浏览器兼容性

        如下为,MDN官方的介绍,可以放心使用window.requestAnimationFrame。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Vue项目中使用requestAnimationFrame实现动画效果的步骤如下: 1. 在Vue组件中,创建一个方法来处理动画效果。例如,我们可以创建一个名为`animate`的方法。 2. 在`animate`方法中,使用`requestAnimationFrame`函数来循环执行动画效果。在每一帧中,你可以更新组件中的数据或者操作DOM元素来实现动画效果。 3. 在`animate`方法中,使用`this.$refs`来获取需要操作的DOM元素。例如,如果你想旋转一个3D模型,你可以使用`this.$refs`来获取模型的引用。 4. 在`animate`方法中,使用`this.$nextTick`来确保DOM元素已经更新完毕。这样可以避免在更新DOM元素之前执行动画效果。 5. 在`animate`方法中,使用`this.$refs`来更新DOM元素的样式或属性。例如,你可以使用`this.$refs.element.style.transform`来旋转一个元素。 6. 在`animate`方法中,使用`requestAnimationFrame`函数来递归调用`animate`方法,以实现动画连续播放。 下面是一个示例代码,演示了如何在Vue项目中使用requestAnimationFrame实现动画效果: ```javascript <template> <div ref="element" class="box"></div> </template> <script> export default { mounted() { this.animate(); }, methods: { animate() { // 更新动画效果 // this.$refs.element.style.transform = 'rotate(45deg)'; // 更新数据 // this.data = 'new data'; // 执行其他操作 // 确保DOM元素已经更新完毕 this.$nextTick(() => { // 更新DOM元素的样式或属性 // this.$refs.element.style.transform = 'rotate(90deg)'; // 执行其他操作 // 递归调用animate方法,实现动画连续播放 requestAnimationFrame(this.animate); }); } } } </script> <style> .box { width: 100px; height: 100px; background-color: red; } </style> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是席木木啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值