Home  >  Article  >  Web Front-end  >  Encapsulation of easing function in JS carousel chart

Encapsulation of easing function in JS carousel chart

高洛峰
高洛峰Original
2017-01-16 14:37:081130browse

The root of the carousel chart is actually the encapsulation of the easing function. If the carousel chart is a running car, then the easing function is its engine. Today, this article will take you from simple to complex, encapsulation Your own easing function~~

We start from the perspective of demand, first give a simple demand:

1. I want a box on the page to move from the starting position to the How to achieve the right movement to 200px?

Analysis:

1) We need to know where the box is, which can be obtained through the offsetLeft attribute;

2) To make the box move at a constant speed, js is definitely required setInterval;

3) Do you want the box to run to the right? That means you need to constantly change the distance between the box and the starting point on the left, including margin-left and positioning left. Here I chose to change the absolute positioning left;

4) Run to a distance of 200px from the starting point If we want to stop, just use clearInterval.

The next step is to go directly to the code

<!DOCTYPE html>
<html>
 <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(&#39;input&#39;),
     dv = document.querySelector(&#39;div&#39;);
   // 添加点击事件
   btn.addEventListener(&#39;click&#39;,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 + &#39;px&#39;; // 最核心的一步,改变盒子的left为当前距离
    },17)
   })
  </script>
 </body>
</html>

2. A preliminary movement effect is achieved, then we improve the requirements:

After the box moves to the position of 200px , do we want the box to continue moving to the 400px position?

Analysis:

1). At this time, there are two buttons to click. One moves to 200px, and the other moves to 400px

2). Although there are two movements, But the functions they use are the same, moving from one point to another, so we consider encapsulating the movement in 1 into a function for reuse.

Code~   

<!DOCTYPE html>
<html>
<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 + &#39;px&#39;;
  }else {
   tag.style.left = target + &#39;px&#39; // 当当前距离与目标距离之间的差值小于step改变的距离时,我们直接让盒子移动到目标距离。
   clearInterval(timer);
   timer = null;
  }
  },17)
 }
 var btns = document.querySelectorAll(&#39;input&#39;),
  dv = document.querySelector(&#39;div&#39;);
 btns[0].addEventListener(&#39;click&#39;,function() {
  animation(dv,200);
 })
 btns[1].addEventListener(&#39;click&#39;,function() {
  animation(dv,400);
 })
 </script>
</body>
</html>

3. We have encapsulated the function for the box to move back and forth, but let’s think about the scrolling effect of the carousel again. It does not move at a constant speed, but at the beginning It's very lumpy, and the speed gradually decreases as the scrolling is nearing completion.

Requirements: Let the box ease (that is, variable speed movement)

Code~

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 + &#39;px&#39;;
  }else {
   tag.style.left = target + &#39;px&#39;
   clearInterval(timer);
   timer = null;
  }
  },17)

Okay, the most basic easing function required for a carousel chart is completed ~

Here is a more complete easing function: its function is more comprehensive and can change multiple styles at the same time.

function perfectAnimate(tag, obj, fn) {// 传三个参数,运动的盒子,对象(可以传多个属性),回调函数(在执行完后可以再执行自定义的功能)
 clearInterval(tag.timer);// 这里将定时器作为tag标签的属性保存,可以多次调用函数清除上一个定时器。
 tag.timer = setInterval(function () {
  var flag = true;
  for (var k in obj) {
       // 因为并不是所有属性都带px单位,所以这里进行判断分别设置 
   if (k == &#39;opacity&#39;) {
    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 == &#39;zIndex&#39;) {
    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 + &#39;px&#39;;
   }
   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];
 }
}

The above is the entire content of this article. I hope it will be helpful to everyone's learning. I also hope that everyone will support the PHP Chinese website.

For more articles related to the encapsulation of easing functions in JS carousel diagrams, please pay attention to the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Previous article:Some tips for JavaScriptNext article:Some tips for JavaScript