最近看到一个腾讯面试题:实现一个div滑动的动画,由快至慢5s结束(不准用css3)。
思路很简单,按照加速度公式,即可实现。
最终的效果:点击链接
捡起高中知识,上公式:
- 可见,只要知道初速度v0,和加速度a,即可知道t秒时刻,路程是多少,即div移动的距离
- 所以,重点是求出v0初速度、a加速度的值,如下图,分别求取v0和a的过程
核心逻辑:
- 支持配置移动距离
- 支持配置移动时间
//匀加速
function speedUp(div1, totalS, totalT) {
let v0 = 0;//初速度
let a = (2 * totalS) / (totalT *totalT) ; //加速度
let startTime = new Date();
let timer = setInterval(function () {
//计算已经过了多少毫秒
let dura = (new Date() - startTime) / 1000;
let s = Math.ceil(v0 * dura + a * dura * dura / 2);
div1.style.left = s+'px';
// if(s >= totalS){//可以按距离来算
if(dura >= totalT){//也可以按时间来算
clearInterval(timer);
}
}, 10)
}
//匀减速
function speedDown(div1, totalS, totalT) {
let v0 = totalS * 2 / totalT;//初速度
let a = -1 * (v0 / totalT); //加速度
let startTime = new Date();
let timer = setInterval(function () {
let dura = (new Date() - startTime) / 1000;
let s = Math.ceil(v0 * dura + a * dura * dura / 2);
div1.style.left = s+'px';
// if(s >= totalS){
if(dura >= totalT){
clearInterval(timer);
}
}, 10)
}
let totalS = 800;//总距离
let totalT = 3; //总时间
speedUp(div1, totalS, totalT);
复制代码
经过封装及公共代码抽离后的完整demo:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<style>
div{
height: 100px;
width: 100px;
margin: 10px 0;
position: relative;
left: 0;
}
</style>
<body>
<table>
<tr>
<td>
匀加速:
</td>
<td>
<div id="div1" style="background: skyblue;" ></div>
</td>
</tr>
<tr>
<td>
匀减速:
</td>
<td>
<div id="div2" style="background: lightpink;"></div>
</td>
</tr>
<tr>
<td>
总路程:
</td>
<td>
<input id="totalS" value="500">px
</td>
</tr>
<tr>
<td>
总时长:
</td>
<td>
<input id="totalT" value="2">s
</td>
</tr>
</table>
<button type="button" id="button">开始</button>
</body>
<script>
let totalSDom = document.getElementById('totalS');
let totalTDom = document.getElementById('totalT');
let timer1 = null;
let timer2 = null;
document.getElementById('button').addEventListener('click', function(){
console.log("111");
clearInterval(timer1);
clearInterval(timer2);
let totalS = totalSDom.value;//总距离 800px
let totalT = totalTDom.value; //总时间,单位秒
let div1 = document.getElementById('div1');
let div2 = document.getElementById('div2');
timer1 = speedUp(div1, totalS, totalT);
timer2 = speedDown(div2, totalS, totalT);
});
//匀减速
function speedUp(div, totalS, totalT) {
let v0 = totalS * 2 / totalT;//初速度
let a = -1 * (v0 / totalT); //加速度
return animation(v0, a, totalT, function(s){
div.style.left = s+'px';
});
}
//匀加速
function speedDown(div, totalS, totalT) {
let v0 = 0;//初速度
let a = (2 * totalS) / (totalT *totalT) ; //加速度
return animation(v0, a, totalT, function(s){
div.style.left = s+'px';
});
}
/**
* @param
* v0: 初速度
* a: 加速度
* totalT:总时长
* callback:回调函数
* **/
function animation(v0, a, totalT, callback){
let startTime = new Date();
let timer = setInterval(function () {
//计算已经过了多少毫秒
let dura = (new Date() - startTime) / 1000;
//计算出移动的距离
let s = Math.ceil(v0 * dura + a * dura * dura / 2);
//回调
callback && callback(s);
// if(s >= totalS){//可以按距离来算
if(dura >= totalT){//也可以按时间来算
clearInterval(timer);
}
}, 50);
return timer;
}
</script>
</html>
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END