七.动画函数
7.1动画实现原理:
动画是通过定时器setInterval()不断移动盒子位置
(1)匀速动画
盒子当前位置+固定步长值
(2)缓动动画
盒子当前值+变化的步长值【(目标值-现在盒子位置)/10】
(3)思路
①获得盒子当前距离
element.offset
②在盒子当前位置上+1
element.sytle.left = element.offset+1+'px'
③定时器不断重复
window.setInterval方法
④最后结束该定时器
clearInterval('定时器名')
- 清除定时器
⑤注意要加定位,才可以使用element.style.left
postion:absolute
【盒子移动示例】:
<style> div{ position: absolute; left: 0; width: 200px; height: 250px; background-color: bisque; } </style> <body> <div></div> <script> //1.获得盒子当前位置 var div = document.querySelector('div'); //2.定时器让其不断动 var timer = window.setInterval(function(){ //3.达到条件 if(div.offsetLeft >= 400){ //停止动画,停止定时器 clearInterval(timer); } //4.不断向右移动 div.style.left = div.offsetLeft + 5 + 'px'; },30); </script>
7.2匀速动画简单封装
注意函数需要传递2个参数:动画对象(obj)和移动到的距离(target)
- 便于设置不同元素的动画效果:
- 调用函数要注意+定位
(1)第一版
//1.封装的动画函数,obj目标对象 target目标位置 function animate(obj,target){ //2.设置定时器 var timer = window.setInterval(function(){ //3.达到条件 if(obj.offsetLeft >= target){ //停止动画,停止定时器 clearInterval(timer); } //4.不断向右移动 obj.style.left = obj.offsetLeft + 1 + 'px'; },30); }
①缺点:
原先var timer每调用一次就需要开辟一个内存空间
同时多个对象的定时器都叫timer,不易区分
(2)第二版
②改进:
将timer变成对象属性
易于区分xxx的timer
function animate(obj,target){ //变为属性的形式 obj.timer = window.setInterval(function(){ if(obj.offsetLeft >= target){ clearInterval(obj.timer); } obj.style.left = obj.offsetLeft+3+'px'; },30); }
(3)第三版-最终
①封装动画函数animate,传入obj目标对象、target目标位置
funtion animate(obj,target)
-
清除原先定时器函数
- clearInterval(obj.timer)
-
对象属性的形式==>开启定时器
obj.timer = window.setInterval(function(){
//判断是否到目标位置
if(obj.offsetLeft >= target)
-
到了目标位置-->停止定时器
clearInterval(obj.timer);
-
没到目标位置-->接着走(+1,带单位)
obj.style.left = obj.offsetLeft + 1 +'px';
},15)
-
②点击按钮动画异常
解决点击按钮调用动画函数,出现点击次数越多,移动速度越快的情况。
- 因为开启了太多定时器
【解决方案:1️⃣每次开启定时器前,将原先的给清除,只保留一个定时器执行2️⃣同时移动要放在if else中,否则点一下会走一步】
<button>点击再走</button> <div></div> <script> var div = document.querySelector('div'); var button = document.querySelector('button'); //1.封装的动画函数,obj目标对象 target目标位置 function animate(obj,target){ //①清除原先定时器 clearInterval(obj.timer); //②不声明变量,变为对象属性的形式 obj.timer = window.setInterval(function(){ //③如果,到了目标位置--》停止定时器 if(obj.offsetLeft >= target){ clearInterval(obj.timer); }else{//④如果没有到目标位置--》移动 obj.style.left = obj.offsetLeft+3+'px'; } },15); } button.addEventListener('click',function(){ animate(div,300); })
7.3缓动动画效果原理
让元素运动的速度变化,常见:慢慢停下;
【思路】:
①让盒子每次移动距离慢慢变小,使速度慢慢落下
②核心算法=(目标值-现在位置)/ 10 =每次移动的距离步长
- 步长=(target- div.offsetLeft)/10
- 步长判断正负:【能往返移动】
- 正,向上取整。Math.ceil((target-div.offsetLeft)/10)
- 负,向下取整。Math.floor((target-div.offsetLeft)/10)
③停止条件:当前盒子位置=目标盒子位置,就停止
- 匀速动画:盒子位置>= 目标盒子位置,就停止
var div = document.querySelector('div'); var btn500 = document.querySelector('.btn500'); var btn800 = document.querySelector('.btn800'); //1.封装的动画函数,obj目标对象 target目标位置 function animate(obj,target){ //①先清除之前的定时器 clearInterval(obj.timer); //②利用对象属性定义定时器 obj.timer = window.setInterval(function(){ //③计算步长:目标距离-目标对象左边距 var step = (target - obj.offsetLeft)/10; //步长差值为正->向上取整;步长差值为负-->向下取整 step = step > 0? Math.ceil(step) : Math.floor(step); //④是否到达目标距离 if(obj.offsetLeft == target){ clearInterval(obj.timer);//到达,清除定时器 }else{ obj.style.left = obj.offsetLeft + step +'px';//未到达,走 } },30); } //2.绑定按钮事件 btn500.addEventListener('click',function(){ animate(div,500); }) btn800.addEventListener('click',function(){ animate(div,800); })
7.4动画函数添加回调函数
(1)回调函数:
将函数作为一个参数传入另一函数中,当函数执行后再执行传入的函数,此过程称为回调
(2)作用:
向动画函数中添加回调函数,可使得执行完动画函数后,再去执行回调函数中的操作。
(3)思路:
①将动画函数 animate(obj,target,callback),其中callback为新加的参数,即传入的回调函数。
- 以此动画函数执行结束---》停止定时器后,再去执行回调函数的操作
②停止定时器后,if判断是否存在callback参数
- 存在:callback( ); 调用该函数
- 不存在:正常执行
③向动画函数传入参数的写法
animate(目标对象,目标位置,function(){回调函数执行的操作});
-
示例
【点击按钮滑动,滑动结束后盒子颜色变绿】
<button class="btn500">点击到500</button> <button class="btn800">点击到800</button> <div></div> <script> var div = document.querySelector('div'); var btn500 = document.querySelector('.btn500'); var btn800 = document.querySelector('.btn800'); //1.封装的动画函数,obj目标对象 target目标位置,callback回调函数 function animate(obj,target,callback){ clearInterval(obj.timer); obj.timer = window.setInterval(function(){ var step = (target - obj.offsetLeft)/10; step = step > 0? Math.ceil(step) : Math.floor(step); if(obj.offsetLeft == target){ clearInterval(obj.timer); //判断是否有callback参数传入 if(callback){ callback(); } }else{ obj.style.left = obj.offsetLeft + step +'px';//未到达,走 } },30); } //2.绑定按钮事件,传入参数 btn800.addEventListener('click',function(){ animate(div,800,function(){ div.style.backgroundColor = 'green'; }); }) </script>
【示例】淘宝侧边栏左右滑动
- 调用的动画函数js代码
//1.封装的动画函数,obj目标对象 target目标位置 function animate(obj,target,callback){ //①先清除之前的定时器 clearInterval(obj.timer); //②利用对象属性定义定时器 obj.timer = window.setInterval(function(){ //③计算步长:目标距离-目标对象左边距 var step = (target - obj.offsetLeft)/10; //步长差值为正->向上取整;步长差值为负-->向下取整 step = step > 0? Math.ceil(step) : Math.floor(step); //④是否到达目标距离 if(obj.offsetLeft == target){ clearInterval(obj.timer);//到达,清除定时器 if(callback){ callback(); } }else{ obj.style.left = obj.offsetLeft + step +'px';//未到达,走 } },15); }
- html+css+js页面实现
- mouseenter鼠标经过
- mouseleave鼠标离开
- 该鼠标事件,不会冒泡,仅元素本身点击有效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .sliderbar { position: fixed; right: 0; bottom: 100px; width: 40px; height: 40px; text-align: center; line-height: 40px; cursor: pointer; color: #fff; background-color: black; } .con { position: absolute; left: 0; top: 0; width: 200px; height: 40px; background-color: purple; z-index: -1; } </style> </head> <body> <div class="sliderbar"> <span>←</span> <div class="con">问题反馈</div> </div> <script src="动画函数.js"></script> <script> // 1. 获取元素 var sliderbar = document.querySelector('.sliderbar'); var con = document.querySelector('.con'); // 2.当我们鼠标经过 sliderbar 就会让 con这个盒子滑动到左侧 con.addEventListener('mouseenter',function(){ console.log(sliderbar.children[0]); //①让con滑动到sliderbar左侧 //②距离=con的宽度-sliderbar的宽度 animate(con,-160,function(){//③回调函数:滑出变为→ sliderbar.children[0].innerHTML = '→'; }); }) // 3.当我们鼠标离开 sliderbar 就会让 con这个盒子滑动到右侧 con.addEventListener('mouseleave',function(){ //①由滑出的-160到0 animate(con,0,function(){//③回调函数:滑回变为← sliderbar.children[0].innerHTML = '←'; }); }) </script> </body> </html>