JS轮播图中缓动函数的封装
轮播图的根本其实就是缓动函数的封装,如果说轮播图是一辆跑动的汽车,那么缓动函数就是它的发动机,今天本文章就带大家由简入繁,封装属于自己的缓动函数~~
我们从需求的角度开始,首先给出一个简单需求:
1、我想让页面中的一个盒子从开始的位置匀速向右运动到200px的地方,该怎么实现?
分析:
1)我们需要知道盒子在哪个地方,这个可以通过offsetLeft属性去获取;
2)要让盒子匀速运动,对于js肯定需要setInterval了;
3)要让盒子向右边跑起来?那就是需要不停改变盒子与左边起始点的距离,有margin-left,还有定位的left,这里我选择了改变绝对定位的left;
4)跑到离开始点200px的距离我们要停下来,使用clearInterval就可以了。
接下来直接上代码了
<!DOCTYPEhtml> <htmllang="en"> <head> <metacharset="UTF-8"/> <title>Document</title> <styletype="text/css"> *{ margin:0; padding:0; } div{ position:absolute; top:50px; width:100px; height:100px; background-color:red; } input{ width:100px; height:30px; color:#fff; background-color:yellowgreen; } </style> </head> <body> <div></div> <inputtype="button"value="移动到200"/> <scripttype="text/javascript"> //获取到元素(这里有个小细节,如果给元素设置了id名,即便不使用获取元素的方法,也能通过这个id名获取到元素哦~~大家可以自己尝试一下) varbtn=document.querySelector('input'), dv=document.querySelector('div'); //添加点击事件 btn.addEventListener('click',function(){ vartimer=null,//保存定时器 currentDistance=dv.offsetLeft,//当前离父盒子的距离 step=8,//每次改变的距离 target=200;//目标距离 timer=setInterval(function(){ currentDistance+=step;//当前距离=上一个当前距离+改变的距离 if((target-currentDistance)<step){ currentDistance=target;//如果目标距离与当前距离的差小于了要改变的距离,这时候我们就直接让当前距离等于目标距离,防止盒子停下来的时候有误差 clearInterval(timer);//清楚定时器 timer=null;//将timer解绑,释放内存 } dv.style.left=currentDistance+'px';//最核心的一步,改变盒子的left为当前距离 },17) }) </script> </body> </html>
2、一个初步运动的效果实现了,那么接下来我们改进了需求:
盒子运动到200px的位置后,我们要让盒子继续运动到400px的位置?
分析:
1)、这时候要有两个按钮点击,一个运动到200px,一个运动到400px
2)、虽然有两个运动,但是其使用的功能都是一样,都是从一个点移动到另一个点,所以我们考虑将1中的运动封装一个函数,以供复用。
上代码~
<!DOCTYPEhtml> <htmllang="en"> <head> <metacharset="UTF-8"/> <title>Document</title> <styletype="text/css"> *{ margin:0; padding:0; } div{ position:absolute; top:50px; width:100px; height:100px; background-color:red; } input{ width:100px; height:30px; color:#fff; background-color:yellowgreen; } </style> </head> <body> <div></div> <inputtype="button"value="移动到200"/> <inputtype="button"value="移动到400"/> <scripttype="text/javascript"> //封装函数,盒子和目标距离都是不确定的,我们可以将他们作为参数传递。 functionanimation(tag,target){ vartimer=null, currentDistance=tag.offsetLeft, step=5; step=currentDistance<target?step:-step;//判断step的正负,200到400时是递增,400到200时是递减 timer=setInterval(function(){ if(Math.abs(currentDistance-target)>Math.abs(step)){//这里判断条件也要略作改动,使用绝对值进行比较 currentDistance+=step;/ tag.style.left=currentDistance+'px'; }else{ tag.style.left=target+'px'//当当前距离与目标距离之间的差值小于step改变的距离时,我们直接让盒子移动到目标距离。 clearInterval(timer); timer=null; } },17) } varbtns=document.querySelectorAll('input'), dv=document.querySelector('div'); btns[0].addEventListener('click',function(){ animation(dv,200); }) btns[1].addEventListener('click',function(){ animation(dv,400); }) </script> </body> </html>
3、盒子来回运动的函数我们封装好了,但是我们再想一下轮播图的滚动效果,它并不是匀速移动,而是最开始很块,在接近滚动完成时,速度又逐渐减低。
需求:让盒子缓动(也就是变速运动)
上代码~
functionanimation(tag,target){ vartimer=null; timer=setInterval(function(){ varcurrentDistance=tag.offsetLeft, step=(target-currentDistance)/5;//通过目标距离与当前距离的差除以5便达到了我们需要的变速运动,因为step每次定制器执行都要改变,所以放入定时器内 step=step>0?Math.ceil(step):Math.floor(step);//这里如果将currentDistance定时器外面声明可以不用写,如果放在定时器内声明,因为offsetLeft取整的特性,要对step进行取整 if(Math.abs(currentDistance-target)>Math.abs(step)){ currentDistance+=step; tag.style.left=currentDistance+'px'; }else{ tag.style.left=target+'px' clearInterval(timer); timer=null; } },17)
好了,一个轮播图需要的最基本的缓动函数完成了~
这里补充一个比较完整的缓动函数:它的功能更全面一点,可以同时更改多样式。
functionperfectAnimate(tag,obj,fn){//传三个参数,运动的盒子,对象(可以传多个属性),回调函数(在执行完后可以再执行自定义的功能) clearInterval(tag.timer);//这里将定时器作为tag标签的属性保存,可以多次调用函数清除上一个定时器。 tag.timer=setInterval(function(){ varflag=true; for(varkinobj){ //因为并不是所有属性都带px单位,所以这里进行判断分别设置 if(k=='opacity'){ varcurrentDistance=getStyle(tag,k)*100, target=obj[k]*100, step=(target-currentDistance)/10; step=step>0?Math.ceil(step):Math.floor(step); currentDistance+=step; tag.style[k]=currentDistance/100; }elseif(k=='zIndex'){ tag.style[k]=obj[k]; else{ varcurrentDistance=parseInt(getStyle(tag,k))||0, target=obj[k], step=(target-currentDistance)/10; step=step>0?Math.ceil(step):Math.floor(step); currentDistance+=step; tag.style[k]=currentDistance+'px'; } if(target!=currentDistance){ flag=false//只要还有属性没有运动完成,就不会清楚定时器 } } if(flag){ clearInterval(tag.timer) fn&&fn();//所有定时器走完,这里执行回调函数,短路操作避免不传回调函数也不会报错。 } },17) }
//获取样式的兼容函数,上面的缓动函数的依赖 functiongetStyle(tag,attr){ if(tag.currentStyle){ returntag.currentStyle[attr]; }else{ returngetComputedStyle(tag,null)[attr]; } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。