原生JS焦点轮播图实现

这是根据网上的教程写的,教程讲的调理很清晰,所以我想把它一步步写下来,算作是一篇笔记吧。脑子笨就要多看多写。奋斗

html结构和css样式

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>焦点轮播图</title>
    <style type="text/css">
        *{ margin: 0; padding: 0; text-decoration: none;}
        body { padding: 20px;}
        #container { width: 600px; height: 400px; border: 3px solid #333; overflow: hidden; position: relative;}
        #list { width: 4200px; height: 400px; position: absolute; z-index: 1;}
        #list img { float: left;}
        #list div{ width: 600px;height: 400px;float: left;}
        #buttons { position: absolute; height: 10px; width: 100px; z-index: 2; bottom: 20px; left: 250px;}
        #buttons span { cursor: pointer; float: left; border: 1px solid #fff; width: 10px; height: 10px; border-radius: 50%; background: #333; margin-right: 5px;}
        #buttons .on {  background: orangered;}
        .arrow { cursor: pointer; display: none; line-height: 39px; text-align: center; font-size: 36px; font-weight: bold; width: 40px; height: 40px;  position: absolute; z-index: 2; top: 180px; background-color: RGBA(0,0,0,.3); color: #fff;}
        .arrow:hover { background-color: RGBA(0,0,0,.7);}
        #container:hover .arrow { display: block;}
        #prev { left: 20px;}
        #next { right: 20px;}
    </style>
</head>
<body>

<div id="container">
    <div id="list" style="left: -600px;">
        <!--<img src="img/5.jpg" alt="1"/>-->
        <!--<img src="img/1.jpg" alt="1"/>-->
        <!--<img src="img/2.jpg" alt="2"/>-->
        <!--<img src="img/3.jpg" alt="3"/>-->
        <!--<img src="img/4.jpg" alt="4"/>-->
        <!--<img src="img/5.jpg" alt="5"/>-->
        <!--<img src="img/1.jpg" alt="5"/>-->
        <div style="background-color: #e4b9b9">1</div>
        <div style="background-color: #e4b9b9">1</div>
        <div style="background-color: #e460b6">2</div>
        <div style="background-color: #e4e13f">3</div>
        <div style="background-color: #4689e4">4</div>
        <div style="background-color: #47e4ad">5</div>
        <div style="background-color: #47e4ad">5</div>
    </div>
    <div id="buttons">
        <span index="1" class="on"></span>
        <span index="2"></span>
        <span index="3"></span>
        <span index="4"></span>
        <span index="5"></span>
    </div>
    <a href="javascript:;" id="prev" class="arrow"><</a>
    <a href="javascript:;" id="next" class="arrow">></a>
</div>

</body>
</html>


实现原理

功能:点击左右箭头左右滑动显示不同图片,点击小按钮显示对应图片,鼠标移出图片范围实现自动播放。

技能点:DOM操作,定时器,函数递归,事件运用,JS动画,无限滚动

要实现一个完整功能的焦点轮播图效果,我们可以按照这几个步骤来进行:

  • 箭头切换
  • 无限滚动
  • 按钮切换
  • 函数动画
  • 自动播放

1. 箭头切换

    点击左右箭头,图片相应方向切换显示。

    代码片段1:

       window.οnlοad=function(){
            var container=document.getElementById("container");
            var list=document.getElementById("list");
            var buttons=document.getElementById("buttons").getElementsByTagName("span");
            var prev=document.getElementById("prev");
            var next=document.getElementById("next");
            
            next.οnclick=function(){
                list.style.left = parseInt(list.style.left) - 600 + "px";
            }
            prev.οnclick=function(){
                list.style.left = parseInt(list.style.left) + 600 + "px";
            }    
        }
    图片容器list的left起始值是-600px,而每张图片的宽度也是600px,所以当我们点击next箭头时希望下一张图片显示就要给list.style.left减去600px;反方向的话就是加上600px;

    这里我们发现

listy.style.left = parseInt(list.style.left) + 600
    这个值其实我们可以放在一个函数里面来调用,减少代码量,称为封装。代码片段1可以重写为这样:

        window.οnlοad=function(){
            var container=document.getElementById("container");
            var list=document.getElementById("list");
            var buttons=document.getElementById("buttons").getElementsByTagName("span");
            var prev=document.getElementById("prev");
            var next=document.getElementById("next");            
            
            function animate(offset){
            	list.style.left = parseInt(list.style.left) + offset + "px";
            }            
            next.οnclick=function(){
            	animate(-600);
            }
            prev.οnclick=function(){
            	animate(600);
            }
        }
     这里我们创建了animate函数,给它一个offset参数,点击向前向后调用animate函数,实现图片的切换。

     到此为止箭头切换这一步就实现了,但是我们发现,当点击切换到最后一张图片再点击时,图片变成了空白,而我们需要切换到最后一张图片再点击时显示的是第一张图片,要实现这种功能,我们就需要进行 无限滚动操作。

2.  无限滚动

     这里只要弄清楚无限滚动的原理其实很简单,我们这个DEMO中为第一张和最后一张添加了与之相同的附属图。当list的偏移值小于-600,也就是当前图片为第一张图片再向前切换的时候,要实现无限滚动,只需要把最后一张图显示出来就好了,也就是说让list的偏移值为-3000就行了。所以,要实现无限滚动,animate方法需要这样改写:

            function animate(offset){
                var newLeft = parseInt(list.style.left) + offset;
            	list.style.left = newLeft + "px";
                if(newLeft > -600){
                    list.style.left = -3000 + "px";
                }
                if(newLeft < -3000){
                    list.style.left = -600 + "px";
                }
            }
      这时候左右切换基本就实现了,但我们发现左右切换的时候,这些小圆点按钮应该也随之对应切换,这里我们就需要添加新的方法showButton()

            var index=1;//用来存放当前显示的图片小圆点

            function showButton(){ //给对应的小圆点添加class,而其他的小圆点去掉样式
                for(var i=0;i<buttons.length;i++){
                    if(buttons[i].className=="on"){
                        buttons[i].className = "";
                        break;
                    }
                }
                buttons[index-1].className="on";
            }
       在点击切换方法中这样调用

            next.οnclick=function(){
                if(index==5){  //当到第5张即最后一张图片时将index重置为1,即返回第一张图片
                    index =1;
                }else{
                    index += 1;
                }
                showButton();
            	animate(-600);
            }
            prev.οnclick=function(){
                if(index==1){
                    index =5;
                }else{
                    index -= 1;
                }
                showButton();
            	animate(600);
            }
这样我们就是实现了无限滚动,并且小圆点也随之对应变化。而我们还希望当点击任意小圆点的时候也应该显示对应图片,这里我们就需要添加一个按钮切换方法。

3.   按钮切换

点击任意小圆点的时候也应该显示对应图片。

我们就需要判断点击的小圆点与图片的对应索引应该相同。这里我们需要注意,正常按顺序一张张切换的时候,每点击一次list的偏移量就加上或者减去600px;不按顺序的时候,list的偏移量就应该是: -600*(目标index值-当前index值)。

            for (var i = 0; i < buttons.length; i++) {
                buttons[i].onclick = function () {
                    var myIndex=parseInt(this.getAttribute("index"));
                    var offset= -600 * (myIndex-index);
                    animate(offset);
                    index=myIndex;
                    showButton();
                }
            }
这样按钮切换就基本完成,但是还有一点小BUG,点击当前小圆点的时候,图片又会刷新一遍,于是我们要做一些小改动:
            for (var i = 0; i < buttons.length; i++) {
                buttons[i].onclick = function () {
                    if(this.className=="on"){
                        return;
                    }
                    var myIndex=parseInt(this.getAttribute("index"));
                    var offset= -600 * (myIndex-index);
                    animate(offset);
                    index=myIndex;
                    showButton();
                }
            }

到这里按钮点击切换就完成了。

4.   函数动画

 我们不希望切换的时候是整张图片而是慢慢的平滑的切换,这里就需要将动画函数进行改动:

           function animate(offset) {
                var newLeft = parseInt(list.style.left) + offset;
                var time=300;//位移总时间
                var interval=10;//位移间隔时间
                var speed=offset/(time/interval); //每次位移量

                function go(){
                    if((speed<0 && parseInt(list.style.left)>newLeft) ||(speed>0 && parseInt(list.style.left)<newLeft)){
                        list.style.left = speed + parseInt(list.style.left) + "px";
                        setTimeout(go,interval);//
                    }
                    else{
                        list.style.left = newLeft + "px";
                        if (newLeft > -600) {
                            list.style.left = -3000 + "px";
                        }
                        if (newLeft < -3000) {
                            list.style.left = -600 + "px";
                        }
                    }

                }
                go();
            }
这里用到了递归函数的知识点,简单将就是在函数体内调用本函数。

当我们不停点击切换的时候,图片不停地切换,这样会造成卡顿的现象,我们需要进行改动,当一张图片完全显示以后才能再次点击切换,当每次动画结束时点击切换才会调用animate()方法。添加一个变量 animated初始值为flase;然后进行判断。

           var animated=false;

           function animate(offset) {
                animated=true;
                var newLeft = parseInt(list.style.left) + offset;
                var time=300;//位移总时间
                var interval=10;//位移间隔时间
                var speed=offset/(time/interval); //每次位移量

                function go(){
                    if((speed<0 && parseInt(list.style.left)>newLeft) ||(speed>0 && parseInt(list.style.left)<newLeft)){
                        list.style.left = speed + parseInt(list.style.left) + "px";
                        setTimeout(go,interval);//
                    }
                    else{
                        animated=false;
                        list.style.left = newLeft + "px";
                        if (newLeft > -600) {
                            list.style.left = -3000 + "px";
                        }
                        if (newLeft < -3000) {
                            list.style.left = -600 + "px";
                        }
                    }

                }
                go();
            }

            next.onclick = function () {
                if (animated) {
                    return;
                }
                if (index == 5) {  //当到第5张即最后一张图片时将index重置为1,即返回第一张图片
                    index = 1;
                } else {
                    index += 1;
                }
                showButton();
                animate(-600);
            }
            prev.onclick = function () {
                if (animated) {
                    return;
                }
                if (index == 1) {
                    index = 5;
                } else {
                    index -= 1;
                }
                showButton();
                animate(600);
            }

            for (var i = 0; i < buttons.length; i++) {
                buttons[i].onclick = function () {
                    if (animated) {
                        return;
                    }
                    if(this.className=="on"){
                        return;
                    }
                    var myIndex=parseInt(this.getAttribute("index"));
                    var offset= -600 * (myIndex-index);
                    animate(offset);
                    index=myIndex;
                    showButton();
                }
            }
5.   自动播放

通常我们希望某些时候图片可以自动切换,我们就需要添加新的方法。

每隔固定时间自动点击切换按钮,这就是自动播放的原理。就需要用到定时器setInterval();

            var interval=3000;
            var timer;
            function play(){
                timer=setInterval(function(){next.onclick();},interval);
            }
            function stop(){
                clearInterval(timer);//清除定时器
            }
            container.οnmοuseοver=stop;
            container.οnmοuseοut=play;

            play();

这里我们发现了新的定时器setInterval,这和之前的setTimeout有什么区别呢?

setInterval在执行完一次代码之后,经过了那个固定的时间间隔,它还会自动重复执行代码

setTimeout只执行一次那段代码。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

完整焦点轮播图代码JS

     window.οnlοad=function() {
            var container = document.getElementById("container");
            var list = document.getElementById("list");
            var buttons = document.getElementById("buttons").getElementsByTagName("span");
            var prev = document.getElementById("prev");
            var next = document.getElementById("next");
            var index = 1;//用来存放当前显示的图片小圆点
            var animated=false;
            var interval=3000;
            var timer;

            function showButton() { //给对应的小圆点添加class,而其他的小圆点去掉样式
                for (var i = 0; i < buttons.length; i++) {
                    if (buttons[i].className == "on") {
                        buttons[i].className = "";
                        break;
                    }
                }
                buttons[index - 1].className = "on";
            }

            function animate(offset) {
                animated=true;
                var newLeft = parseInt(list.style.left) + offset;
                var time=300;//位移总时间
                var interval=10;//位移间隔时间
                var speed=offset/(time/interval); //每次位移量

                function go(){
                    if((speed<0 && parseInt(list.style.left)>newLeft) ||(speed>0 && parseInt(list.style.left)<newLeft)){
                        list.style.left = speed + parseInt(list.style.left) + "px";
                        setTimeout(go,interval);//
                    }
                    else{
                        animated=false;
                        list.style.left = newLeft + "px";
                        if (newLeft > -600) {
                            list.style.left = -3000 + "px";
                        }
                        if (newLeft < -3000) {
                            list.style.left = -600 + "px";
                        }
                    }
                }
                go();
            }

            function play(){
                timer=setInterval(function(){next.onclick();},interval);
            }
            function stop(){
                clearInterval(timer);//清除定时器
            }

            next.onclick = function () {
                if (animated) {
                    return;
                }
                if (index == 5) {  //当到第5张即最后一张图片时将index重置为1,即返回第一张图片
                    index = 1;
                } else {
                    index += 1;
                }
                showButton();
                animate(-600);
            }
            prev.onclick = function () {
                if (animated) {
                    return;
                }
                if (index == 1) {
                    index = 5;
                } else {
                    index -= 1;
                }
                showButton();
                animate(600);
            }

            for (var i = 0; i < buttons.length; i++) {
                buttons[i].onclick = function () {
                    if (animated) {
                        return;
                    }
                    if(this.className=="on"){
                        return;
                    }
                    var myIndex=parseInt(this.getAttribute("index"));
                    var offset= -600 * (myIndex-index);
                    animate(offset);
                    index=myIndex;
                    showButton();
                }
            }

            container.οnmοuseοver=stop;
            container.οnmοuseοut=play;

            play();
        }


----------------------------------------------------------------------------------------------------------------------------------------------------------------------

到此为止,我们的这个焦点轮播图就算大功告成了。但是这中方法还是有一定的问题,我们必须为第一张和最后一张图添加对应的附属图,拓展性不是特别强。

第一次写,错误肯定会有,先草草结束吧。










  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值