动画
动画函数的封装需要一点一点拓展、完善,由匀速到可以变速,由单一目标值到多个目标值。。。
动画原理
动画原理:
1:获取盒子的当前位置
2:让盒子在当前位置加上1个移动距离
3:利用定时器 不断重复这个操作
4:加一个结束定时器的条件
5:元素需要添加定位 才能使用element.style.left
/*
obj目标对象
target 目标位置
*/
function animate(obj,target){
clearInterval(obj.timer);
obj.timer = setInterval(function(){
if(obj.offsetLeft >= target){
clearInterval(obj.timer)
}
obj.style.left = obj.offsetLeft + 1 + 'px';
},30)
}
当一个按钮的点击事件绑定该函数时,如果不断点击按钮,盒子会加速,解决这个问题需要在定时器前先清除之前遗留的定时器。
缓动动画原理
缓动动画让元素运动速度有所变化,最常见的是让速度慢慢停下来
思路:
1:让盒子每次移动的距离慢慢变小,速度就会慢慢减下来
2:可以将 (目标位置 - 当前位置) / 10 作为每次移动的距离步长
3:停止的条件 让盒子当前位置等于目标位置 就停止定时器
4:步长值需要取整
function animate(obj,target){
clearInterval(obj.timer);
obj.timer = setInterval(function(){
// 求步长 步长要写到定时器
var step = (target - obj.offsetLeft) /10;
// 步长向上取整 变为1 到最后(目标值-当前位置) 小于10时 步长变为1px 1px的移动
step = Math.ceil(step)
//console.log(step,1)
if(obj.offsetLeft == target){
// console.log(123)
clearInterval(obj.timer)
}
// 把每次加1这个步长的值改为一个慢慢变小的值 步长公式:(目标位置 - 当前位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
},15)
}
多个目标值之间移动
让动画从100移动到800,再移动到1000,再移动到500
(目标位置 - 当前位置) / 10
100-----500 目标值 > 当前位置 步长 正值 Math.ceil 向上取整
800-----300 目标值 < 当前位置 步长 负值 -0.4 ===> -1 Math.floor 向下取整
function animate(obj,target){
clearInterval(obj.timer);
obj.timer = setInterval(function(){
var step = (target - obj.offsetLeft) /10;
// 步长向上取整 变为1 到最后(目标值-当前位置) 小于10时 步长变为1px 1px的移动
step = step > 0 ? Math.ceil(step) : Math.floor(step)
if(obj.offsetLeft == target){
clearInterval(obj.timer)
}
// 把每次加1这个步长的值改为一个慢慢变小的值 步长公式:(目标位置 - 当前位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
},15)
}
var oDiv = document.querySelector('div');
var oBtn1 = document.querySelector('.btn1');
var oBtn2 = document.querySelector('.btn2');
oBtn1.addEventListener('click',function(){
animate(oDiv,100)
})
oBtn2.addEventListener('click',function(){
animate(oDiv,500)
})
回调函数
函数作为一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完后,再执行传进去的这个函数,这个过程叫做回调
说白了,回调函数是一个作为参数传递给另一个JavaScript函数的函数。
补充:短路
语句fn && fn()
,意思是如果fn()函数存在则调用它。
JS中短路运算符&&和||
动画函数封装
animate.js :
/*
obj目标对象
target 目标位置
*/
function animate(obj,target,callback){
clearInterval(obj.timer);
obj.timer = setInterval(function(){
// 求步长 步长要写到定时器
var step = (target - obj.offsetLeft) /10;
// 步长向上取整 变为1 到最后(目标值-当前位置) 小于10时 步长变为1px 1px的移动
step = step > 0 ? Math.ceil(step) : Math.floor(step)
console.log(step,1)
if(obj.offsetLeft == target){
// console.log(123)
// 清除定时器--- 最后执行的代码
clearInterval(obj.timer);
// 此处要执行不同的代码
// alert("我到终点了");
// 回调函数要写在定时器结束里
callback && callback()
// if(callback){
// callback()
// }
}
// 把每次加1这个步长的值改为一个慢慢变小的值 步长公式:(目标位置 - 当前位置) / 10
obj.style.left = obj.offsetLeft + step + 'px';
},15)
}
回调函数和动画的案例
.box{
position: fixed;
right: 0;
bottom: 200px;
width: 40px;
height: 40px;
text-align: center;
line-height: 40px;
color: #fff;
}
.question{
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 40px;
background-color: red;
z-index: -1;
}
<div class="box">
<span><-</span>
<div class="question">我有问题</div>
</div>
/* 引入本地动画封装js */
<script src="./js/animate.js"></script>
var oBox = document.querySelector('.box')
var question = document.querySelector('.question')
oBox.addEventListener('mouseenter',function(){
animate(question,-160,function(){
oBox.children[0].innerHTML = '->';
})
})
oBox.addEventListener('mouseleave',function(){
animate(question,-0,function(){
oBox.children[0].innerHTML = '<-';
})
})