Bootstrap

javascript轮播图超详细

主要功能介绍:

鼠标移动到轮播图中显示左右按钮,轮播图片的定时器停止

鼠标移出轮播图隐藏左右按钮,轮播图片的定时器开始

动态创建下面的小圆点

无缝滚动效果

点击左右按钮能切换图片,点击小圆点也能切换到对应的图片中,定时器切换图片

使用时间阀,只有点击左右按钮图片运动完成之后,点击左右按钮才能再次滚动,防止点击左右按钮次数过多,图片滚动过快的情况

 1、先搭建框架,标签如下图所示

2、html和css代码如下图所示,简单写一下,重要是学习js代码

    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        div {
            box-sizing: border-box;
        }
        
        .focus {
            margin: 0 auto;
            position: relative;
            width: 1200px;
            height: 600px;
            background-color: pink;
            overflow: hidden;
        }
        
        ul {
            position: absolute;
            /* margin-left: 100px; */
            width: 8000px;
            height: 600px;
        }
        
        ul li {
            float: left;
            width: 1200px;
            height: 600px;
            background-color: purple;
            overflow: hidden;
        }
        
        img {
            width: 100%;
        }
        
        span {
            position: absolute;
            width: 60px;
            height: 60px;
            background-color: rgba(0, 0, 0, .5);
            color: #fff;
            font-size: 40px;
            text-align: center;
            line-height: 60px;
            top: 40%;
            z-index: 2;
            cursor: move;
        }
        
        .left {
            display: none;
            left: 0;
        }
        
        .right {
            display: none;
            left: 1138px;
        }
        
        ol {
            position: absolute;
            top: 550px;
            left: 50%;
            height: 40px;
            background-color: rgba(0, 0, 0, .2);
            list-style: none;
            transform: translate(-50%);
            border-radius: 20px;
            padding: 0 20px;
        }
        
        ol li {
            float: left;
            width: 20px;
            height: 20px;
            border-radius: 10px;
            background-color: #fff;
            margin-top: 10px;
            margin-left: 15px;
        }
        
        .current {
            background-color: orange;
        }
    </style>
    <script src="animate.js"></script>
    <script src="轮播.js"></script>
</head>

<body>
    <div class="focus">
        <span class="left">&lt</span>
        <span class="right">&gt</span>

        <ul>
            <li>
                <a href="javascript:;"><img src="1.jpg" alt=""></a>
            </li>
            <li>
                <a href="javascript:;"><img src="2.jpg" alt=""></a>
            </li>
            <li>
                <a href="javascript:;"><img src="3.jpg" alt=""></a>
            </li>
            <li>
                <a href="javascript:;"><img src="4.jpg" alt=""></a>
            </li>
        </ul>
        <ol>

        </ol>
    </div>

三、javascript代码如下

赶时间直接复制版:

导包:这是自己写的一个js代码文件,名字命名为animate.js

function animate(obj, target, callback) {
    // 写到创建定时器前面,始终让定时器,做多只有一个。
    clearInterval(obj.timer);
    obj.timer = setInterval(function() {
        // 当box左边距离page的距离大于target的时候,就清除计时器。
        // 但一点击就会又调用一次这个函数,就会又创建一次定时器,
        // 定时器存在就会不停向右移动

        // 只有达到极值(目的目标)时才会清除定时器。
        var step = (target - obj.offsetLeft) / 10;
        if (step >= 0) {
            step = Math.ceil(step);
        } else {
            step = Math.floor(step);
        };
        if (obj.offsetLeft == target) {
            clearInterval(obj.timer);
            // 当他清除定时器时,说明所有的都已经执行完毕,再写回调函数就是所有的执行完,他才执行
            if (callback) {
                callback();
            }
            // callback && callback();
        }
        // console.log('obj.offsetLeft:' + obj.offsetLeft);
        // console.log('step:' + step);
        // console.log('target' + target);
        obj.style.left = (obj.offsetLeft + step) + 'px';
    }, 50);


}

轮播图代码: 

window.addEventListener('load', function() {
    var spanLeft = document.querySelector('.left');
    var spanRight = document.querySelector('.right');
    var focus = document.querySelector('.focus');
    var ol = this.document.querySelector('ol');
    var ul = focus.querySelector('ul');
    // 鼠标经过focus区域,左右两边的按钮显示
    focus.addEventListener('mouseenter', function() {
        spanLeft.style.display = 'block';
        spanRight.style.display = 'block';
        // 当鼠标经过focus区域的时候,清除定时器
        clearInterval(timer);
        timer = null;
    });
    // 鼠标离开focus区域,左右两边的按钮隐藏
    focus.addEventListener('mouseleave', function() {
        spanLeft.style.display = 'none';
        spanRight.style.display = 'none';
        // 离开focus时开启定时器(这里就不用var timer 了,直接给timer赋一个函数即可)
        timer = setInterval(function() {
            // 手动调用点击事件  目标对象.事件类型()
            spanRight.click();
        }, 2000)
    });
    // 动态创建小圆圈li并将他添加到ol中
    for (var i = 0; i < ul.children.length; i++) {
        // 每循环一次,创建一个li(不能创建一个li添加多次)
        var li = document.createElement('li');
        ol.appendChild(li);
        // 每创建一个li就给他创建一个自定义属性
        li.setAttribute('index', i);
        // 点击的这个li(不点击不会触发,当点击时早已经生成完毕)
        // 点击li让ul移动相应的距离
        li.addEventListener('click', function() {
            // 排他思想
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            this.className = 'current';
            // 获取被点击li的自定义属性index的值
            var index = this.getAttribute('index');
            // 当我们点击了某个li时,就把这个li的索引值index给num
            // 让点击的小圆圈和点击左右按钮移动图片联系起来
            //不然,如果点击第三个小圆圈,下面的小圆点到第三个,再点击右按钮,
            // 他又会按照点击右按钮的算法,给num赋值为2,让小圆点到第二个上去
            num = index;
            // 当我们点击了某个li时,就把这个li的索引值index给circle
            // 让点击的小圆圈和点击左右按钮,下面的小圆点也跟着动联系起来
            circle = index;
            // 注意ul没有position:absolute;就不能移动,原理就是靠改变绝对定位的值来改变位置的
            animate(ul, -index * focus.offsetWidth);
        });

    };
    // 先给ol里面的第一个小圆圈一个current属性,让圆圈不点击情况下,默认颜色为橘色
    ol.children[0].className = 'current';
    // 深度克隆第一个li,为了实现动态的无缝连接
    // 克隆的放到生成ol>li的后面,不然就会多生成一个li,影响效果
    var first = ul.children[0].cloneNode(true);
    // 将第一个li添加到ul的后面,他又在创建小圆圈的后面,所以不用多创建一个小圆圈
    ul.appendChild(first);
    // 点击一次右侧按钮,就让图片往右移动一个li的距离
    // 让左右按钮和ul图片移动联系起来
    var num = 0;
    // 定义一个全局变量circle,当点击左右切换按钮时,下面的小圆点也跟着动
    var circle = 0;
    // 定义一个flag变量,用节流阀来防止图片切换过快的现象
    var flag = true;
    spanRight.addEventListener('click                                  ', function() {
        // 点击按钮后,先让他进入if判断语句执行,进入后把路给他封上,
        // 再当所有的动画都执行完毕后,即用回调函数再把路给他打开
        if (flag) {
            flag = false;
            num++;
            // num是从0开始的,他最多到ul.children.length-1个,当num=(children.length-1)+1时,
            // 说明又得循环一次。    比如有4个li,再加上克隆的,一共有5个。num最大到4(从0开始)
            // 当num等于5时,让他的位置迅速的到num= 0的位置(肉眼看不见的移动),此时再让num = 1,再进行
            // 一次动画,相当于无缝连接
            // 时,返回开头,从0开始无缝滚动
            if (num == ul.children.length) {
                ul.style.left = 0;
                num = 1;
            }
            // 添加回调函数,等动画都执行完毕再执行回调函数即让他可以点击按钮,切换图片
            animate(ul, -num * focus.offsetWidth, function() {
                flag = true;
            });
            // 先++,因为点击后切换到第二个li,给第二个小圆点current才行
            // 让左右按钮和下面的小圆圈联系起来
            circle++;
            // 排他思想
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            // 一共有四个圈,circle从0开始,最大到3,让他的圈等4时,强制circle等于0,就实现循环
            if (circle == ol.children.length) {
                circle = 0;
            }
            // 让第circle+1个圈有橙色的类名
            ol.children[circle].className = 'current';
        }


    });
    // 点击一次左边的按钮,先num--如果他等于-1,也就是说一个循环结束,他该换到最后一张图片了
    // 就迅速把他的最后一张的ul的left值用style.left的方式赋值给ul,
    // 当他迅速(肉眼看不到的速度)切换到最后一张克隆的照片时,让num=最后一张照片的前一个值,
    // 再做一次动画,将ul的left值,减少一个li的大小======> 无缝滚动原理
    spanLeft.addEventListener('click', function() {
            if (flag) {
                num--;
                if (num == -1) {
                    // 当num= -1时,让ul迅速到达第5图,即num= 4时<=>ul.children.length - 1
                    // 再让他往前做一次动画------->无缝连接
                    ul.style.left = -(ul.children.length - 1) * focus.offsetWidth;
                    num = ul.children.length - 2;
                }
                animate(ul, -num * focus.offsetWidth, function() {
                    flag = true;
                });
                circle--;
                // 排他思想
                for (var i = 0; i < ol.children.length; i++) {
                    ol.children[i].className = '';
                }
                if (circle == -1) {
                    circle = ol.children.length - 1;
                }
                ol.children[circle].className = 'current';
            }
        })
        // 自动播放轮播图
    var timer = this.setInterval(function() {
        // 手动调用点击事件  目标对象.事件类型()
        spanRight.click();
    }, 1000);




})

详细解析版:

1、 鼠标经过focus区域,左右两边的按钮显示

       鼠标离开focus区域,左右两边的按钮隐藏

这一块不是很难,当你想要做轮播图的时候,这就已经很简单了。

  window.addEventListener('load', function() {
    var spanLeft = document.querySelector('.left');
    var spanRight = document.querySelector('.right');
    var focus = document.querySelector('.focus');
    // 鼠标经过focus区域,左右两边的按钮显示
    focus.addEventListener('mouseenter', function() {
        spanLeft.style.display = 'block';
        spanRight.style.display = 'block';
       
    });
    // 鼠标离开focus区域,左右两边的按钮隐藏
    focus.addEventListener('mouseleave', function() {
        spanLeft.style.display = 'none';
        spanRight.style.display = 'none';
   
    });

2、动态创建小圆圈li并将他添加到ol中(ol中的小圆圈的数目不能固定,所以要动态添加)

    //获取小圆圈的ol和轮播图中的ul
    var ol = this.document.querySelector('ol');
    var ul = focus.querySelector('ul');
    for (var i = 0; i < ul.children.length; i++) {
        // 每循环一次,创建一个li(不能创建一个li添加多次)
        var li = document.createElement('li');
        ol.appendChild(li);
    }
  // 先给ol里面的第一个小圆圈一个current属性,让圆圈不点击情况下,默认颜色为橘色
    ol.children[0].className = 'current';

 3、点击下方的小圆圈,就切换图片(实质是让ul移动相应的距离),当前小圆点的颜色也改变

注意:这个操作可以在上述操作中进行,这步操作在点击之后才会运行,当你点击时,上述操作早已经执行完毕

   //获取小圆圈的ol和轮播图中的ul
    var ol = this.document.querySelector('ol');
    var ul = focus.querySelector('ul');
    for (var i = 0; i < ul.children.length; i++) {
        // 每循环一次,创建一个li(不能创建一个li添加多次)
        var li = document.createElement('li');
        ol.appendChild(li);
        
        // 每创建一个li就给他创建一个自定义属性
        li.setAttribute('index', i);
        // 点击的这个li(不点击不会触发,当点击时上述早已经生成完毕)
        // 点击li让ul移动相应的距离
        li.addEventListener('click', function() {
            // 排他思想,让所有的li的className全消失,让当前的classname出现
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            this.className = 'current';
            // 获取被点击li的自定义属性index的值
            var index = this.getAttribute('index');
            animate(ul, -index * focus.offsetWidth);
        });
        
    }

4、为了实现无缝连接,需要深度克隆第一li并将它放到ul最后面的位置

深度克隆:var  first = li.cloneNode(true);

在元素后添加:父级.appendChild(子级);

    ol.children[0].className = 'current';
    // 深度克隆第一个li,为了实现动态的无缝连接
    // 克隆的放到生成ol>li的后面,不然就会多生成一个li,影响效果
    var first = ul.children[0].cloneNode(true);
    // 将第一个li添加到ul的后面,他又在创建小圆圈的后面,所以不用多创建一个小圆圈
    ul.appendChild(first);

5、点击左右按钮实现图片的切换效果

// 定义一个flag变量,用节流阀来防止图片切换过快的现象
    var flag = true;
    spanRight.addEventListener('click', function() {
        // 点击按钮后,先让他进入if判断语句执行,进入后把路给他封上,
        // 再当所有的动画都执行完毕后,即用回调函数再把路给他打开
        if (flag) {
            flag = false;
            num++;
            // num是从0开始的,他最多到ul.children.length-1个,当num=(children.length-1)+1时,
            // 说明又得循环一次。    比如有4个li,再加上克隆的,一共有5个。num最大到4(从0开始)
            // 当num等于5时,让他的位置迅速的到num= 0的位置(肉眼看不见的移动),此时再让num = 1,再进行
            // 一次动画,相当于无缝连接
            // 时,返回开头,从0开始无缝滚动
            if (num == ul.children.length) {
                ul.style.left = 0;
                num = 1;
            }
            // 添加回调函数,等动画都执行完毕再执行回调函数即让他可以点击按钮,切换图片
            animate(ul, -num * focus.offsetWidth, function() {
                flag = true;
            });
            // 先++,因为点击后切换到第二个li,给第二个小圆点current才行
            // 让左右按钮和下面的小圆圈联系起来
            circle++;
            // 排他思想
            for (var i = 0; i < ol.children.length; i++) {
                ol.children[i].className = '';
            }
            // 一共有四个圈,circle从0开始,最大到3,让他的圈等4时,强制circle等于0,就实现循环
            if (circle == ol.children.length) {
                circle = 0;
            }
            // 让第circle+1个圈有橙色的类名
            ol.children[circle].className = 'current';
        }


    });
    // 点击一次左边的按钮,先num--如果他等于-1,也就是说一个循环结束,他该换到最后一张图片了
    // 就迅速把他的最后一张的ul的left值用style.left的方式赋值给ul,
    // 当他迅速(肉眼看不到的速度)切换到最后一张克隆的照片时,让num=最后一张照片的前一个值,
    // 再做一次动画,将ul的left值,减少一个li的大小======> 无缝滚动原理
    spanLeft.addEventListener('click', function() {
            if (flag) {
                num--;
                if (num == -1) {
                    // 当num= -1时,让ul迅速到达第5图,即num= 4时<=>ul.children.length - 1
                    // 再让他往前做一次动画------->无缝连接
                    ul.style.left = -(ul.children.length - 1) * focus.offsetWidth;
                    num = ul.children.length - 2;
                }
                animate(ul, -num * focus.offsetWidth, function() {
                    flag = true;
                });
                circle--;
                // 排他思想
                for (var i = 0; i < ol.children.length; i++) {
                    ol.children[i].className = '';
                }
                if (circle == -1) {
                    circle = ol.children.length - 1;
                }
                ol.children[circle].className = 'current';
            }
        })

 

 6、创建定时器实现自己滚动

  // 自动播放轮播图
    var timer = this.setInterval(function() {
        // 手动调用点击事件  目标对象.事件类型()
        spanRight.click();
    }, 1000);

7、当鼠标放到focus时,清除定时器。当鼠标移开focus时,创建定时器。

这一步是在第一步的基础上完成的

    // 鼠标经过focus区域,左右两边的按钮显示
    focus.addEventListener('mouseenter', function() {
        spanLeft.style.display = 'block';
        spanRight.style.display = 'block';
        // 当鼠标经过focus区域的时候,清除定时器
        clearInterval(timer);
        timer = null;
    });
    // 鼠标离开focus区域,左右两边的按钮隐藏
    focus.addEventListener('mouseleave', function() {
        spanLeft.style.display = 'none';
        spanRight.style.display = 'none';
        // 离开focus时开启定时器(这里就不用var timer 了,直接给timer赋一个函数即可)
        timer = setInterval(function() {
            // 手动调用点击事件  目标对象.事件类型()
            spanRight.click();
        }, 2000)
    });

8、让几个步骤联系起来

            // 当我们点击了某个li时,就把这个li的索引值index给num
            // 让点击的小圆圈和点击左右按钮移动图片联系起来
            //不然,如果点击第三个小圆圈,下面的小圆点到第三个,再点击右按钮,
            // 他又会按照点击右按钮的算法,给num赋值为2,让小圆点到第二个上去
            num = index;
            // 当我们点击了某个li时,就把这个li的索引值index给circle
            // 让点击的小圆圈和点击左右按钮,下面的小圆点也跟着动联系起来
            circle = index;
            // 注意ul没有position:absolute;就不能移动,原理就是靠改变绝对定位的值来改变位置的

;