js原生轮播图

爱⌒轻易说出口 提交于 2019-11-25 19:35:27

思路:首先要知道需求,先从简单的地方入手,然后一步一步的去改进,但是首先要想好做每一步目的,原因,不要只知道代码是这么写的,而不去想为什么要这么做。

动画函数封装

 function animate(obj, target, callback) { //做动画的对象,需要移动的距离,回调函数
            clearInterval(obj.timer);
            obj.timer = setInterval(function() {
                var step = (target - obj.offsetLeft) / 10;//缓动动画实现原理
                step = step > 0 ? Math.ceil(step) : Math.floor(step); //取整的问题,否者后面会有瑕疵
                if(obj.offsetLeft == target){  //判断时候到达位置
                    clearInterval(obj.timer); //清除定时器
                    obj.timer = null; //将该对象的定时器设置为空,释放内存
                    callback && callback(); //如果有回调函数就调用回调函数
                }
                obj.style.left = obj.offsetLeft + step + 'px'; //移动
            }, 15);
        }

1,首先获取几个等会肯定要用到的元素;

	    var arrowLeft = document.querySelector('.arrow-l');  //获取左右两个小箭头
        var arrowRight = document.querySelector('.arrow-r');
        var focus = document.querySelector('.center'); //获取父盒子
        var focusWidth = focus.offsetWidth;  //得到父盒子的宽度,一会图片的切换需要用到
        var ul = focus.querySelector('ul');//获取ul,为ol动态创建li做准备
        var ol = focus.querySelector('ol');

2,原先左右的两个小箭头是隐藏的,只有当鼠标经过了它们所在的父盒子,它们才会显示,所以可以为 focus 添加监听事件了

focus.addEventListener('mouseenter', function() {        //当鼠标经过时显示
            arrowRight.style.display = arrowLeft.style.display = 'block';
});

 focus.addEventListener('mouseleave',  function() {     //离开隐藏
            arrowRight.style.display = arrowLeft.style.display = 'none';
  }

3,一般到了后面会不确定每次的轮播图的图片有几张,所以与图片所对应的小圆点建议动态的创建,根据图片的个数,来创建对应的圆点个数

for(var i = 0; i < ul.children.length; i++){
            var li = document.createElement('li');
            li.setAttribute('index', i);//再创建li的同时给它设置一个索引号,后面会用到
            li.addEventListener('click', fn3);//再给它们添加点击事件
            ol.appendChild(li);  //追加到ol中
 }
 function fn3() {   //点击每个小圆点所做的事
      for(var i = 0; i < ol.children.length; i++){  //排他思想,将所有的小圆点的样式都先去掉
            ol.children[i].className = '';  
       }
      var index = this.getAttribute('index');  //获取图片的索引值
      animate(ul, -index * focusWidth);//开始做移动效果,根据你所点击的小圆点的索引值,
      	//乘以一个盒子的宽度,就是ul索要移动的距离,
      this.className = 'current'; //再设置你所点击的小圆点的样式
 }
 ol.children[0].className = 'current'; //默认的显示为第一张图片,所以要设置第一个小圆点的样式

4,添加点击左侧按钮事件,

		ul.appendChild(ul.children[0].cloneNode(true)); //克隆第一张图片,做无缝切换,
        //一定要放在创建小圆点的后面,因为小圆点的跳转比较简单,不用做无缝切换,
        var num = 0;  //为了来控制图片所再的位置
        var circle = 0;   //为了来控制与图片所对应的小圆点的样式 
        arrowLeft.addEventListener('click', fn4);   //添加点击事件
        function fn4() { 
          if(num == 0){    //判断如果当前图片是不是第一张,
               num = ul.children.length - 1;  //如果时就将num等于我们克隆出来的图片的位置,也就是最后一个
               ul.style.left = -num * focusWidth + 'px';   //立马将ul移动到最后一张图片,不做动画效果
           }
           num--; //--了以后就是指向真正的最后一张图片,就是原始的最后一张
           circle--;  //小圆点的位置也要发生改变 
           if(circle < 0){  //判断--了以后是否小于零了
               circle = ol.children.length - 1;  //如果小于零了就将它设为最后一个小圆点的索引
           }	
           for(var i = 0; i < ol.children.length; i++){  //还是排他思想,
                ol.children[i].className = '';//去掉其他所有的样式
            }
            ol.children[circle].className = 'current'; //给当前索引的小圆点添加样式
            animate(ul, -num * focusWidth);//做动画
     	}

5,因为有的用户会直接点击小圆点,然后再点击左右箭头,所以会导致num个circle的值不准,所以我们要做个修改,再小圆点的点击方法里该

function fn3() {   //点击每个小圆点所做的事
      for(var i = 0; i < ol.children.length; i++){  //排他思想,将所有的小圆点的样式都先去掉
            ol.children[i].className = '';  
       }
      var index = this.getAttribute('index');  //获取图片的索引值。
      num=circle=index;  //将你所点击的索引值同步给num和circle就可以解决了
      animate(ul, -index * focusWidth);//开始做移动效果,根据你所点击的小圆点的索引值,
      	//乘以一个盒子的宽度,就是ul索要移动的距离,
      this.className = 'current'; //再设置你所点击的小圆点的样式
 }

6,为右侧添加点击事件 大部分的原理与左侧相同,所以我就不做过多的解释了

arrowRight.addEventListener('click',fn5);
        function fn5() {
                if(num==ul.children.length-1){  //因为是右移,所以时判断是不是最后一张图(克隆出来的图片)
                    num=0;  
                    ul.style.left=-num*focusWidth+'px';  //是的话立马进行跳转至第一张图
                }
                num++;
                circle++;
                if(circle==ol.children.length){
                    circle=0;  //与上面同理
                }
               for(var i = 0; i < ol.children.length; i++){  //还是排他思想,
             	   ol.children[i].className = '';//去掉其他所有的样式
          	    }
                animate(ul,-num*focusWidth)
            
        }

7,给页面添加自动轮播的方法,就是添加一个定时器,然后每次自动调用右侧点击按钮事件就可以了,不用再重新写一份代码了

var timer=setInterval(function() {
            arrowRight.click();
},2000);    //超级简单

8,根据这些代码,可以完成动画了,但是这样子有一个缺点,就是当用户非常快的点击左右两侧的按钮,图片也会跳转的非常的快,所以我们要做一个节流阀,就是为了防止用户点击过快,用户每次点击两侧按钮,需要等上一次所点击的动画完成后才有效,做起来非常简单

var flag=true; //声明一个切换true与false的变量

然后再每个点击事件里面首先做一个判断,flag是否为真,为真就进入做动画,做动画前将flag改为false,再动画做完后做一个回调函数,这个回调函数里面就写flag=true
以点击右侧为例:

 arrowRight.addEventListener('click',fn5);
        function fn5() {
            if(flag){ //判断
                flag=false;  //修该, 如果用户点击过快,上一次的动画还没结束,flag都为false,
                	//就不能再进入了,也就不能开始做动画了
                if(num==ul.children.length-1){
                    num=0;
                    ul.style.left=-num*focusWidth+'px';
                }
                num++;
                circle++;
                if(circle==ol.children.length){
                    circle=0;
                }
                circleChange(); //我将这里原先的代码封装起来了,左右两侧的代码相同
                animate(ul,-num*focusWidth,function(){flag=true}) //等动画做完后执行这个回调函数,将flag改为true,就可以再进行下一次的动画了
            }
        }

整个页面代码如下 (有些与上面的不同是我做了一些小的优化)

<!DOCTYPE html>
<html lang="zh_CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        a{
            text-decoration: none;
            color: white;
        }
        li{
            list-style: none;
        }
        .center{
            position: relative;
            width: 721px;
            margin: auto;
            overflow: hidden;
            height: 455px;
        }
        .center ul{
            position: absolute;
            width: 500%;
        }
        .center ul li{
            float: left;
        }
        .arrow-l, .arrow-r{
            display: none;
            width: 24px;
            height: 40px;
            text-align: center;
            line-height: 40px;
            background-color: rgba(0, 0, 0, .3);
            color: white;
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            z-index: 2;
        }
        .arrow-l{
            border-top-right-radius: 50%;
            border-bottom-right-radius: 50%;
        }
        .arrow-r{
            right: 0;
            border-top-left-radius: 50%;
            border-bottom-left-radius: 50%;
        }
        .circle{
            position: absolute;
            bottom: 10px;
            left: 50px;
        }
        .circle li{
            float: left;
            width: 8px;
            height: 8px;
            /*background-color: #fff;*/
            border: 2px solid rgba(255, 255, 255, 0.5);
            margin: 0 3px;
            border-radius: 50%;
            /*鼠标经过显示小手*/
            cursor: pointer;
        }
        .current{
            background-color: #fff;
        }
    </style>
</head>
<body>
    <div class="center">
        <a href="javascript:;" class="arrow-l">&lt;</a>
        <a href="javascript:;" class="arrow-r">&gt;</a>
        <ul>
            <li>
                <a href="javascript:;"><img src="img/focus.jpg" alt=""></a>
            </li>
            <li>
                <a href="javascript:;"><img src="img/focus1.jpg" alt=""></a>
            </li>
            <li>
                <a href="javascript:;"><img src="img/focus2.jpg" alt=""></a>
            </li>
            <li>
                <a href="javascript:;"><img src="img/focus3.jpg" alt=""></a>
            </li>
        </ul>
        <ol class="circle"></ol>
    </div>
    <script>
        function animate(obj, target, callback) {
            clearInterval(obj.timer);
            obj.timer = setInterval(function() {
                var step = (target - obj.offsetLeft) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if(obj.offsetLeft == target){
                    clearInterval(obj.timer);
                    obj.timer = null;
                    callback && callback();
                }
                obj.style.left = obj.offsetLeft + step + 'px';
            }, 15);
        }
        var arrowLeft = document.querySelector('.arrow-l');  //获取左右两个小箭头
        var arrowRight = document.querySelector('.arrow-r');
        var focus = document.querySelector('.center');
        var focusWidth = focus.offsetWidth;
        var ul = focus.querySelector('ul');//获取ul,为ol动态创建li做准备
        var ol = focus.querySelector('ol');

        focus.addEventListener('mouseenter', fn1);
        function fn1() {
            arrowRight.style.display = arrowLeft.style.display = 'block';
            clearInterval(timer);
            timer=null;
        }

        focus.addEventListener('mouseleave', fn2);
        function fn2() {
            arrowRight.style.display = arrowLeft.style.display = 'none';
            timer=setInterval(function() {
                arrowRight.click();
            },2000);
        }

        for(var i = 0; i < ul.children.length; i++){
            var li = document.createElement('li');
            li.setAttribute('index', i);
            li.addEventListener('click', fn3);
            ol.appendChild(li);
        }
        function fn3() {
            if(flag){
                flag=false;
                for(var i = 0; i < ol.children.length; i++){
                    ol.children[i].className = '';
                }
                var index = this.getAttribute('index');
                num = circle = index;
                animate(ul, -num * focusWidth,function(){flag=true});
                this.className = 'current';
            }
        }
        ol.children[0].className = 'current';

        ul.appendChild(ul.children[0].cloneNode(true)); //克隆第一张图片,做无缝切换
        var num = 0;
        var circle = 0;
        var flag = true;
        arrowLeft.addEventListener('click', fn4);
        function fn4() {
            if(flag){
                flag=false;
                if(num == 0){
                    num = ul.children.length - 1;
                    ul.style.left = -num * focusWidth + 'px';
                }
                num--;
                circle--;
                if(circle < 0){
                    circle = ol.children.length - 1;
                }
                circleChange();
                animate(ul, -num * focusWidth,function() {flag=true});
            }
        }

        arrowRight.addEventListener('click',fn5);
        function fn5() {
            if(flag){
                flag=false;
                if(num==ul.children.length-1){
                    num=0;
                    ul.style.left=-num*focusWidth+'px';
                }
                num++;
                circle++;
                if(circle==ol.children.length){
                    circle=0;
                }
                circleChange();
                animate(ul,-num*focusWidth,function(){flag=true})
            }
        }

        var timer=setInterval(function() {
            arrowRight.click();
        },2000);
        function circleChange() {
            for(var i = 0; i < ol.children.length; i++){
                ol.children[i].className = '';
            }
            ol.children[circle].className = 'current';
        }
    </script>
</body>
</html>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!