欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JS轮播图中缓动函数的封装

程序员文章站 2023-11-11 13:13:40
轮播图的根本其实就是缓动函数的封装,如果说轮播图是一辆跑动的汽车,那么缓动函数就是它的发动机,今天本文章就带大家由简入繁,封装属于自己的缓动函数~~ 我们从需求的角度开始...

轮播图的根本其实就是缓动函数的封装,如果说轮播图是一辆跑动的汽车,那么缓动函数就是它的发动机,今天本文章就带大家由简入繁,封装属于自己的缓动函数~~

我们从需求的角度开始,首先给出一个简单需求:

1、我想让页面中的一个盒子从开始的位置匀速向右运动到200px的地方,该怎么实现?

分析:

1)我们需要知道盒子在哪个地方,这个可以通过offsetleft属性去获取;

 2)要让盒子匀速运动,对于js肯定需要setinterval了;

3)要让盒子向右边跑起来?那就是需要不停改变盒子与左边起始点的距离,有margin-left,还有定位的left,这里我选择了改变绝对定位的left;

 4)跑到离开始点200px的距离我们要停下来,使用clearinterval就可以了。 

接下来直接上代码了  

<!doctype html>
<html lang="en">
 <head>
  <meta charset="utf-8" />
  <title>document</title>
  <style type="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>
  <input type="button" value="移动到200" />


  <script type="text/javascript">
   // 获取到元素(这里有个小细节,如果给元素设置了id名,即便不使用获取元素的方法,也能通过这个id名获取到元素哦~~大家可以自己尝试一下)
   var btn = document.queryselector('input'),
     dv = document.queryselector('div');
   // 添加点击事件
   btn.addeventlistener('click',function() {
    var timer = 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中的运动封装一个函数,以供复用。

上代码~   

<!doctype html>
<html lang="en">
<head>
 <meta charset="utf-8" />
 <title>document</title>
 <style type="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>
 <input type="button" value="移动到200" />
 <input type="button" value="移动到400" />
 <script type="text/javascript">
 // 封装函数,盒子和目标距离都是不确定的,我们可以将他们作为参数传递。
 function animation(tag,target) {
  var timer = 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)
 }
 var btns = 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、盒子来回运动的函数我们封装好了,但是我们再想一下轮播图的滚动效果,它并不是匀速移动,而是最开始很块,在接近滚动完成时,速度又逐渐减低。

需求: 让盒子缓动(也就是变速运动) 

上代码~    

function animation(tag,target) {
  var timer = null;
  timer = setinterval(function() {
  var currentdistance = 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)

好了,一个轮播图需要的最基本的缓动函数完成了~ 

这里补充一个比较完整的缓动函数:它的功能更全面一点,可以同时更改多样式。  

function perfectanimate(tag, obj, fn) {// 传三个参数,运动的盒子,对象(可以传多个属性),回调函数(在执行完后可以再执行自定义的功能)
 clearinterval(tag.timer);// 这里将定时器作为tag标签的属性保存,可以多次调用函数清除上一个定时器。
 tag.timer = setinterval(function () {
  var flag = true;
  for (var k in obj) {
       // 因为并不是所有属性都带px单位,所以这里进行判断分别设置 
   if (k == 'opacity') {
    var currentdistance = 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;
   } else if (k == 'zindex') {
    tag.style[k] = obj[k];
   else {
    var currentdistance = 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)
}
// 获取样式的兼容函数,上面的缓动函数的依赖
function getstyle(tag, attr) {
 if (tag.currentstyle) {
  return tag.currentstyle[attr];
 } else {
  return getcomputedstyle(tag, null)[attr];
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。