基于原生Javascript的无缝轮播

一、前言

  • 轮播图的种类

说起轮播图,种类那可是五花八门,什么淡入淡出呀、旋转木马呀、3D轮播呀、无缝轮播呀等等,简直是秀的头皮发麻~
本文要讲的就是其中的无缝轮播,小伙伴们知道是怎么实现的吗,如果不知道的话,嘿嘿,你就接着往下看吧。如果你知道的话,就当捧个场,也往下看吧~

  • 基本要求

html和css完成静态布局、js获取并且操纵元素,定时器的应用,节流函数,日期对象等等。

二、无缝轮播的原理

首先,我们来看看什么是无缝轮播,就像下图所示:
无缝轮播演示
其大概过程就是,上一张图片从左往右(或从右往左离开),下一张图片从左往右(或从右往左)进入。哎呀,貌似很简单的样子,有些小伙伴立马就想到了一个大容器里面有一个ul,ul里面有若干个li并且存放图片,把每个li的宽度设置成和容器同宽,然后每次点击的时候改变ul的left值就行了。嗯,很想很有道理的样子,于是三下五除二就做出来了,但是却发现有点问题,就像下面这样:
演示
从第一张到倒数第二张图片还好,但是从最后一张图片到第一张图片就有问题了,并没有从最后一张图片直接切换到第一张图片,而是经过了中间的图片慢慢过渡到第一张图片(第一张图片到最后一张图片也同理),这显然不是预期的效果。问题既然已经发现了,就要去解决它,那么如何才能达到从最后一张图片直接切换到第一张图片(或第一张到最后一张),也就是无缝的效果,答案很简单,我们需要多一张图片(这张图片和第一张图片是相同的)放在图片列表的最后!为什么需要这样一张图片,请往下看。
我们在上面已经清楚要解决的就是首尾图片间的切换问题,所以在引入多一张图片之后,可以让轮播从倒数第二张图片(在没有引入图片之前的最后一张图片)切换到最后一张图片(新引入的图片)的动画完成之后,再瞬间跳转到第一张图片,请看下图(我把外面容器的overflow:hidden去掉了以便大家理解):

  • 布局

布局

  • 动图演示轮播过程

演示

  • 把overflow:hidden加上,利用视觉差之后

演示
嘿嘿,是不是很神奇,多引入了一张图片我们就把刚才的问题解决了,至于从第一张到最后一张图片的切换,把刚才的过程倒过来就行了。

三、无缝轮播演示

  • 这里我用到了节流函数,如果你还不知道什么是节流函数的话,可以点击下方链接去我另外一篇文章查看。

点我跳转Javascript函数式编程之节流函数

  • 代码部分
/* css代码 */
body{
    background-color: #333;
}
ul{
    position: absolute;
    left: 0;
    list-style: none;
    padding: 0;
}
.wrap{
    overflow: hidden;
    position: relative;
    width: 700px;
    height: 450px;
    margin: 100px auto 0;
}
.wrap .btn{
    position: absolute;
    top: 50%;
    z-index: 1;
    width: 50px;
    height: 80px;
    margin-top: -40px;
    background-color: rgba(0,0,0,.5);
    color: #fff;
    text-align: center;
    line-height: 80px;
    cursor: pointer;
}
.wrap .left{
    left: 0;
}
.wrap .right{
    right: 0;
}
.img-list{
    top: 0;
    margin: 0;
    width: 500%;
    height: 100%;
}
.img-list li{
    float: left;
    width: 700px;
    height: 100%;
}
.img-list li:nth-of-type(1){
    background: url("images/01.jpg") no-repeat center/cover;
}
.img-list li:nth-of-type(2){
    background: url("images/02.png") no-repeat center/cover;
}
.img-list li:nth-of-type(3){
    background: url("images/03.png") no-repeat center/cover;
}
.img-list li:nth-of-type(4){
    background: url("images/04.png") no-repeat center/cover;
}
.img-list li:nth-of-type(5){
    background: url("images/01.jpg") no-repeat center/cover;
}
.tab-list{
    right: 0;
    bottom: 10px;
    width: 100px;
    margin: auto;
}
.tab-list:after{
    content: "";
    display: block;
    clear: both;
}
.tab-list li{
    float: left;
    transition: 1s;
    width: 15px;
    height: 15px;
    margin-left: 5px;
    background-color: #bbb;
    border-radius: 50%;
}
.tab-list li:hover{
    cursor: pointer;
}
.tab-list li:first-child{
    margin-left: 0;
}
.tab-list .on{
    width: 40px;
    border-radius: 8px;
}
<!-- html代码 -->
<div class="wrap">
    <div class="btn left">&lt;</div>
    <div class="btn right">&gt;</div>
    <ul class="img-list">
        <li></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    <ul class="tab-list">
        <li class="on"></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</div>
//js代码
(function(){
        var oImgList = document.getElementsByClassName("img-list")[0],
            aButton = document.getElementsByClassName("btn"),
            aImgLi = document.querySelectorAll(".img-list li"),
            oWidth = parseFloat(getComputedStyle(aImgLi[0]).width),
            oWrap = document.getElementsByClassName("wrap")[0],
            aTab = document.querySelectorAll(".tab-list li");
            len = aImgLi.length,
            index = 0;
        function throttle(fn,time){
            var startTime = new Date();
            return function(){
                var time_ = (new Date() - startTime) >= time;
                if(time_){
                    fn.apply(this);
                    startTime = new Date();
                }
            }
        }
        function btnTab(){
            var t = new Date();
            for(var i = 0,tabLen = aTab.length;i < tabLen;i++){
                (function(i){
                    aTab[i].onclick = function(){
                        if(new Date() - t >= 1000){
                            aTab[index].className = "";
                            if((i - index) === (tabLen - 1)){
                                oImgList.style.transition = 0 + "s";
                                oImgList.style.left = -oWidth*(len-1) + "px";
                                index = len - 2;
                                setTimeout(function(){
                                    oImgList.style.transition = 1 + "s";
                                    oImgList.style.left = -oWidth*(index) + "px";
                                },1000/60);
                            }
                            else if((i - index) === (1 - tabLen)){
                                oImgList.style.left = -oWidth*(len - 1) + "px";
                                index = 0;
                                setTimeout(function(){
                                    oImgList.style.transition = 0 + "s";
                                    oImgList.style.left = index + "px";
                                },1000);
                            }
                            else{
                                oImgList.style.left = -oWidth*(i) + "px";
                                oImgList.style.transition = 1 + "s";
                            }
                            index = i;
                            this.className = "on";
                            t = new Date();
                        }
                    }
                })(i);
            }
        }
        function btnPre(){
            index--;
            if(index < 0){
                oImgList.style.transition = 0 + "s";
                oImgList.style.left = -oWidth*(len-1) + "px";
                aTab[0].className = "";
                index = len - 2;
                aTab[index].className = "on";
                setTimeout(function(){
                    oImgList.style.transition = 1 + "s";
                    oImgList.style.left = -oWidth*(index) + "px";
                },1000/60);
            }
            else{
                oImgList.style.transition = 1 + "s";
                oImgList.style.left = -oWidth*(index) + "px";
                aTab[index + 1].className = "";
                aTab[index].className = "on";
            }
        }
        function btnNext(){
            index++;
            oImgList.style.transition = 1 + "s";
            if(index === len-1){
                oImgList.style.left = -oWidth*index + "px";
                aTab[len - 2].className = "";
                index = 0;
                aTab[index].className = "on";
                setTimeout(function(){
                    oImgList.style.transition = 0 + "s";
                    oImgList.style.left = index + "px";
                },1000);
            }
            else{
                oImgList.style.left = -oWidth*index + "px";
                aTab[index - 1].className = "";
                aTab[index].className = "on";
            }
        }
        aButton[0].onclick = throttle(btnPre,1000);
        aButton[1].onclick = throttle(btnNext,1000);
        btnTab();
        var timer = setInterval(btnNext,5000);
        oWrap.onmouseover = function(){
            clearInterval(timer);
        }
        oWrap.onmouseout = function(){
            timer = setInterval(btnNext,5000);
        }
    })();
  • demo演示

无缝轮播演示demo

四、无缝轮播的改进

在上面的无缝轮播中,可以发现对于不是相邻的两张图片的切换也并不是直接切换的,而是会过渡中间的图片再切换到目标图片,如下图:
演示
解决办法就是把除了当前显示的图片全都设置成display:none,这样做的好处就是display:none的元素不占据位置!比如说从第一张切换到第三张,因为第二张是display:none,第三章需要显示所以display:block,由于第二张图片不占据位置的原因第三张图片会在第一张图片之后,因此就达到了从第一张直接切换到第三张的效果。

  • 动图演示(没有overflow:hidden)

演示
(有overflow:hidden)
演示

  • 改进后的代码
/* css代码 */
body{
    background-color: #333;
}
ul{
    position: absolute;
    left: 0;
    list-style: none;
    padding: 0;
}
.wrap{
    overflow: hidden;
    position: relative;
    width: 700px;
    height: 450px;
    margin: 100px auto 0;
}
.wrap .btn{
    position: absolute;
    top: 50%;
    z-index: 1;
    width: 50px;
    height: 80px;
    margin-top: -40px;
    background-color: rgba(0,0,0,.5);
    color: #fff;
    text-align: center;
    line-height: 80px;
    cursor: pointer;
}
.wrap .left{
    left: 0;
}
.wrap .right{
    right: 0;
}
.img-list{
    top: 0;
    margin: 0;
    width: 500%;
    height: 100%;
}
.img-list li{
    display: none;
    float: left;
    width: 700px;
    height: 100%;
}
.img-list .active{
    display: block;
}
.img-list li:nth-of-type(1){
    background: url("images/01.jpg") no-repeat center/cover;
}
.img-list li:nth-of-type(2){
    background: url("images/02.png") no-repeat center/cover;
}
.img-list li:nth-of-type(3){
    background: url("images/03.png") no-repeat center/cover;
}
.img-list li:nth-of-type(4){
    background: url("images/04.png") no-repeat center/cover;
}
.img-list li:nth-of-type(5){
    background: url("images/01.jpg") no-repeat center/cover;
}
.tab-list{
    right: 0;
    bottom: 10px;
    width: 100px;
    margin: auto;
}
.tab-list:after{
    content: "";
    display: block;
    clear: both;
}
.tab-list li{
    float: left;
    transition: 1s;
    width: 15px;
    height: 15px;
    margin-left: 5px;
    background-color: #bbb;
    border-radius: 50%;
}
.tab-list li:hover{
    cursor: pointer;
}
.tab-list li:first-child{
    margin-left: 0;
}
.tab-list .on{
    width: 40px;
    border-radius: 8px;
}
<!-- html代码 -->
<div class="wrap">
    <div class="btn left">&lt;</div>
    <div class="btn right">&gt;</div>
    <ul class="img-list">
        <li class="active"></li>
        <li></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
    <ul class="tab-list">
        <li class="on"></li>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</div>
//js代码
(function(){
        var oImgList = document.getElementsByClassName("img-list")[0],
            aButton = document.getElementsByClassName("btn"),
            aImgLi = document.querySelectorAll(".img-list li"),
            oWidth = parseFloat(getComputedStyle(aImgLi[0]).width),
            oWrap = document.getElementsByClassName("wrap")[0],
            aTab = document.querySelectorAll(".tab-list li");
            len = aImgLi.length,
            index = 0,
            index_ = 0;
        function throttle(fn,time){
            var startTime = new Date();
            return function(){
                var time_ = (new Date() - startTime) >= time;
                if(time_){
                    fn.apply(this);
                    startTime = new Date();
                }
            }
        }
        function btnTab(){
            var t = new Date(),
                direction;
            for(var i = 0,tabLen = aTab.length;i < tabLen;i++){
                (function(i){
                    aTab[i].onclick = function(){
                        if(new Date() - t >= 1000){
                            index_ = index;
                            i - index > 0 ? direction = true : direction = false;
                            if(this.className !== "on"){
                                aTab[index].className = "";
                                if((i - index) === (tabLen - 1)){
                                    aImgLi[len - 1].className = "active";
                                    aImgLi[0].className = "";
                                    oImgList.style.transition = 0 + "s";
                                    oImgList.style.left = -oWidth + "px";
                                    aTab[0].className = "";
                                    index = len - 2;
                                    aImgLi[index].className = "active";
                                    setTimeout(function(){
                                        oImgList.style.transition = 1 + "s";
                                        oImgList.style.left = 0 + "px";
                                    },1000/60);
                                    setTimeout(function(){
                                        aImgLi[len - 1].className = "";
                                    },1000);
                                }
                                else if((i - index) === (1 - tabLen)){
                                    oImgList.style.transition = 1 + "s";
                                    oImgList.style.left = -oWidth + "px";
                                    aTab[len - 2].className = "";
                                    aImgLi[len - 1].className = "active";
                                    index = 0;
                                    aTab[index].className = "on";
                                    setTimeout(function(){
                                        oImgList.style.transition = 0 + "s";
                                        oImgList.style.left = index + "px";
                                        aImgLi[index].className = "active";
                                        aImgLi[len-2].className = "";
                                        aImgLi[len-1].className = "";
                                    },1000);
                                }
                                else{
                                    if(direction){
                                        oImgList.style.left = -oWidth + "px";
                                        oImgList.style.transition = 1 + "s";
                                        setTimeout(function(){
                                            aImgLi[index_].className = "";
                                            oImgList.style.left = 0 + "px";
                                            oImgList.style.transition = 0 + "s";
                                        },1000);
                                    }
                                    else{
                                        oImgList.style.transition = 0 + "s";
                                        oImgList.style.left = -oWidth + "px";
                                        aImgLi[index].className = "active";
                                        setTimeout(function(){
                                            oImgList.style.transition = 1 + "s";
                                            oImgList.style.left = 0 + "px";
                                        },1000/60);
                                        setTimeout(function(){
                                            aImgLi[index_].className = "";
                                        },1000);
                                    }
                                    index = i;
                                    aImgLi[index].className = "active";
                                }
                                this.className = "on";
                                t = new Date();
                            }
                        }
                    }
                })(i);
            }
        }
        function btnPre(){
            index--;
            if(index < 0){
                aImgLi[len - 1].className = "active";
                aImgLi[0].className = "";
                oImgList.style.transition = 0 + "s";
                oImgList.style.left = -oWidth + "px";
                aTab[0].className = "";
                index = len - 2;
                aImgLi[index].className = "active";
                aTab[index].className = "on";
                setTimeout(function(){
                    oImgList.style.transition = 1 + "s";
                    oImgList.style.left = 0 + "px";
                },1000/60);
                setTimeout(function(){
                    aImgLi[len - 1].className = "";
                },1000);
            }
            else{
                oImgList.style.transition = 0 + "s";
                oImgList.style.left = -oWidth + "px";
                aTab[index + 1].className = "";
                aTab[index].className = "on";
                aImgLi[index].className = "active";
                setTimeout(function(){
                    oImgList.style.transition = 1 + "s";
                    oImgList.style.left = 0 + "px";
                },1000/60);
                setTimeout(function(){
                    aImgLi[index + 1].className = "";
                },1000);
            }
        }
        function btnNext(){
            index++;
            oImgList.style.transition = 1 + "s";
            if(index === len-1){
                oImgList.style.left = -oWidth + "px";
                aTab[len - 2].className = "";
                aImgLi[index].className = "active";
                index = 0;
                aTab[index].className = "on";
                setTimeout(function(){
                    oImgList.style.transition = 0 + "s";
                    oImgList.style.left = index + "px";
                    aImgLi[index].className = "active";
                    aImgLi[len-2].className = "";
                    aImgLi[len-1].className = "";
                },1000);
            }
            else{
                oImgList.style.left = -oWidth + "px";
                aTab[index - 1].className = "";
                aTab[index].className = "on";
                aImgLi[index].className = "active";
                setTimeout(function(){
                    oImgList.style.transition = 0 + "s";
                    aImgLi[index - 1].className = "";
                    oImgList.style.left = 0 + "px";
                },1000);
            }
        }
        aButton[0].onclick = throttle(btnPre,1000);
        aButton[1].onclick = throttle(btnNext,1000);
        btnTab();
        var timer = setInterval(btnNext,5000);
        oWrap.onmouseover = function(){
            clearInterval(timer);
        }
        oWrap.onmouseout = function(){
            timer = setInterval(btnNext,5000);
        }
 })();
  • 改进后的无缝轮播demo演示

改进后的无缝轮播demo演示

五、结束语

本文仅仅提到了无缝轮播,其实还有很多优秀的轮播效果,但是由于目前能力有限,还驾驭不了~所以就到这里啦,总之任重而道远,最后感谢阅读咯~

猜你喜欢

转载自blog.csdn.net/qq_42129063/article/details/82012396
今日推荐