JavaScript-如何通过原生JS实现匀速动画

JavaScript-如何通过原生JS实现匀速动画

据我们所知,我们可以通过css3(transform translate即可)区实现这个动画,但是通常面试的时候,可能会被要求原生手敲;

​ 使用到的知识点:定时器去实现setInterval去实现

js 复制代码
<button onclick="changeBox()">点击移动box</button>
    <div class="box"></div>
    <script>
        let box = document.querySelector('.box')
        let timerId 
        let timerId2
        function changeBox(){
            if(timerId2){clearTimeout(timerId2)}
            timerId2 = setTimeout(()=>{
                // if(timerId){clearInterval(timerId)}
                let original = box.offsetLeft;
                let current = 0
                timerId = setInterval(()=>{
                    current++
                    box.style.left = original + current + 'px'
                    // 比如移动到100px的时候就停止
                    console.log(current === 100,"查看防抖是否生效")
                    if(current === 100){
                        clearInterval(timerId)
                    }
                },10)
            },1000)
        }
    </script>
对于以上代码进行公共封装:元素原生实现匀速动画
js 复制代码
  /**
  * @target <Object> 传入的目标元素
  * @moveData <number> 每次点击移动数据
 * **/
function animate(target, moveData,callback) {
   if (target.timerId) {
       clearInterval(target.timerId)
   }
   let original = target.offsetLeft;
   let current = 0
       target.timerId = setInterval(() => {
         current++
         box.style.left = original + current + 'px'
           if (current === moveData) {
              clearInterval(target.timerId)
              if (callback instanceof Function) {
            	callback()
         	}
           }
         }, 10)
       }
缓动动画封装(匀速、加速、减速、返回加速、返回减速)

前面可以看到,我们使用current++是一种匀速的方式,匀速的快慢取决于我们+=后面的值,如果我们希望是缓动动画的形式去移动我们的元素,我们可以通过以下封装算法去实现

js 复制代码
 /** 清除定时器的时候需要注意的判断,非匀速是会有差别的
* if (current <0  || current == 0) {
     clearInterval(timerId4)
     box.style.left =original + 'px'
	}else{
		box.style.left =original + current + 'px'
     }
 **/function speed (type, moveData) {
  switch (type) {
    case 'uniformSpeed': // 匀速
      function uniformSpeed () {
        let current = 0
        return current++
      }
      return speed++
      break
    case 'moderate': // 减速
      function moderate (moveData) {
        let current = 0
        let distance = moveData - current
        return (current += distance
          ? Math.ceil(distance / 10)
          : Math.floor(distance / 10))
      }
      break
    case 'accelerate': // 加速
      function accelerate (moveData) {
        let current = 0
        let distance = 10 + current
        return current < 500
          ? (current += distance
              ? Math.ceil(distance / 10)
              : Math.floor(distance / 10))
          : 500
      }
      break
    case 'comeBack-accelerate': // 往回加速
      function comeBack (moveData) {
        let current = moveData
        let distance = 10 + current
        current -=
          distance > 0 ? Math.ceil(distance / 10) : Math.floor(distance / 10)
      }
      break
    case 'comeBack-moderate': // 往回减速速
      function comeBack (moveData) {
        let current = 0
        let distance = moveData - current
        return (current -= distance
          ? Math.ceil(distance / 10)
          : Math.floor(distance / 10))
      }
      break
  }
}
相关推荐
kyriewen1 小时前
同事每天催我 Code Review,我写了个脚本让 AI 替我 review PR——现在他反过来催 AI 了
前端·javascript·ai编程
weedsfly4 小时前
迭代器、生成器与异步迭代——让数据“按需流动”的艺术
前端·javascript
假如让我当三天老蒯4 小时前
前端跨域解决方案(学习用)
前端·javascript·面试
铁皮饭盒6 小时前
Bun 哪比 Node.js 快?
javascript·后端
JieE21213 小时前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
candyTong16 小时前
RTK 技术原理:一次典型会话里,80% 上下文是怎么省下来的
javascript·后端·架构
_柳青杨20 小时前
深入理解 JavaScript 事件循环
前端·javascript
大家的林语冰1 天前
ES5 凉凉,Babel 8 正式发布,默认不再编译为 ES5 和 CJS......
前端·javascript·前端工程化
weedsfly1 天前
异步编程全景与事件循环——彻底搞懂 JS 执行机制
前端·javascript
用户1733598075371 天前
纯前端 PDF 数字签名实战:Vue 3 + pdf-lib 在浏览器里完成签名嵌入
前端·javascript