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
}
}