美文网首页
使用JavaScript实现图片轮播效果

使用JavaScript实现图片轮播效果

作者: 黎贝卡beka | 来源:发表于2017-07-05 17:03 被阅读0次

    原理

    图片轮播原理:
    将一系列大小相等的图片平铺,利用css布局只显示一张图片,其他图片隐藏,通过计算偏移量利用定时器自动切换图片,或者手动点击切换图片。

    样式布局

    关于图片列表的布局,这里在js中使用style.left这个属性计算偏移量来进行图片的切换。而在style.left这个属性中,是无法识别样式表中写的left值,只对HTML中写的left值有效.
    关于小圆点按钮,使用自定义属性index来标识第几个小圆点。后边当点击某个小圆点时,可获取该小圆点的index值来知道小圆点的位置。利用css样式使class="on"的元素颜色变亮,即点亮当前点击到的小圆点。
    关于箭头切换,使用链接形式,可以添加hover伪类变换样式。<左箭头;>右箭头,html转义字符。

    无缝切换:最后一张图片切换到第一张图片时,会出现一片空白,这里,借助两张辅助图来填补这片空白。
    即将最后一张图片属性复制到第一张图片前,将第一张图片属性信息复制到最后一张图片后面。
    并且,将第一张图片辅助图(实际上是实际显示的第5张图片隐藏起来,故设置style="left: -600px;"

    <div id="container" >
            <!-- 图片列表 -->
            <div id="list" style="left: -600px">
                ![](img/5.jpg)<!-- 第一张辅助图 -->
                ![](img/1.jpg)
                ![](img/2.jpg)
                ![](img/3.jpg)
                ![](img/4.jpg)
                ![](img/5.jpg)
                ![](img/1.jpg)<!-- 第二张辅助图 -->   
            </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:;" class="arrow" id="prev">&lt;</a>
            <a href="javascript:;" class="arrow" id="next">&gt;</a>
        </div>
    

    css结构:

    1. 绝对定位问题,图片和原点的浮动属性;
    2. overflow: hidden;//溢出隐藏
    3. 确保每个小圆点所在层置顶,(z-index:999;)这里设置为z-index:2; 另外z-index 仅能在定位元素上奏效
    4. cursor CSS属性定义鼠标指针悬浮在元素上方显示的鼠标光标。cursor: pointer显示为小手。
    *{
        margin: 0;
        padding: 0;
        text-decoration: none;
    }
    body{
        padding: 10px;
    }
    #container{
        width: 600px;
        height: 400px;
        border: 3px solid #333;
        overflow: hidden;//溢出隐藏
        position: relative;//定位
    
    }
    #list{
        width: 4200px;//所有图片平铺的宽度
        height: 400px;
        border: 3px solid #333;
        position: absolute;//定位问题 利用偏移量进行切换
        /*z-index: 1;*/
    
        /* transition:left 2s;
        
            -moz-transition:left 2s; Firefox 4
        
            -webkit-transition:left 2s; Safari and Chrome
        
            -o-transition:left 2s; Opera */
    }
    #list img{
        float: left;//浮动(不用清除浮动)
    
    }
    #buttons{
        position: absolute;
        /*height: 20px;
        width: 100px*/
        /*z-index: 2;*/ //层级,使按钮置于顶层
        bottom: 25px;
        left: 250px;
    }
    #buttons span{
        cursor: pointer;/*小手*/
        float: left;//浮动                        
        border: 1px solid #fff;//白边框
        width: 20px;
        height: 20px;
        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,0.3);
        color: #fff;
    }
    .arrow:hover{
        background-color: rgba(0,0,0,0.7);//鼠标移上去颜色加深
    }
    #container:hover .arrow{
        display: block;//鼠标移到盒子上显示箭头
    }
    #prev{
        left: 20px;//单独定义左箭头水平位置
    } 
    #next{
        right: 20px;//单独定义右箭头水平位置
    }
    

    js部分整个功能封装在window.onload事件中。

    箭头切换&无限滚动&动画切换

    先获取元素,添加点击事件。parseInt将字符串转换成数字。
    获取style.left,是相对左边获取距离,且style.left获取的是字符串,需要用parseInt()取整转化为数字。

        next.onclick=function(){
             list.style.left=parseInt(list.style.left)-600+'px';
        }
        prev.onclick=function(){
            list.style.left=parseInt(list.style.left)+600+'px';
        }
    

    封装在函数animate里。并实现循环切换。当切换到第一张辅助图上时,parseInt(list.style.left)的值为0,实际上应该是最后一张图片,所以归为到最后一张图片的位置上list.style.left=-3000+'px';
    同理,当切换到第二张辅助图上时,parseInt(list.style.left)的值为-3600,实际上应该是第一张图片,所以归为到第一张图片的位置上list.style.left=-600+'px';

        //切换图片,利用图片的偏移量
        function animate(offset){
            var newLeft = parseInt(list.style.left)+offset;//值 图片左侧距离父元素的值
            list.style.left=newLeft+'px';//px
            // list.style.left=list.offsetLeft+offset+'px';
            if(newLeft>-600){//和第一张图片位置比较
                list.style.left=-3000+'px';//归位到第五张图片
            }
            if(newLeft<-3000){//和最后一张图片位置比较
                list.style.left=-600+'px';//归位到第一张图片
            }
            // debugger;
    }
    

    实现每次切换图片的过程中,是过渡动画切换的。
    思路:通过自定义位移完一张图片的总时间time和每次位移的时间inteval,来计算图片移动一下的距离speed,直到一张图片完整的移到当前可视的盒子区域。

    animate()函数内定义go()函数,首先判断图片是往哪个方向移,因为如果向左移的话,即传入的偏移量是负值,所以speed < 0,这时候图片左侧距离父元素的值parseInt(list.style.left)是越来越小的,直到为newLeft,结束动画位移,一张图片完整的切换到了可视区域。so只要parseInt(list.style.left) >newLeft,就进行动画位移;

    同理,当图片向右移时,speed >0,这时候图片左侧距离父元素的值parseInt(list.style.left)是越来越大的,直到为newLeft。所以只要parseInt(list.style.left) < newLeft,就进行着动画位移。

    如果满足动画位移条件会一直执行,使用定时器setTimeout(go, inteval),没隔一段时间interval执行一次go
    这里使用了递归,函数内部调用该函数。

    对于定时器,注意setInterval()跟setTimeout()的区别。简单来说,setInterval()执行多次,setTimeout()只执行一次。
    更具体的用法可以点击链接查看区别:window.setInterval window.setTimeout

    这里定义一个初始值var animated = false;,表示默认不进行动画位移,animated = true表示开始动画位置标志。并在结束动画位移操作时,将animated的值置为false。

    function animate (offset) {
             animated = true;//开始动画位移
             var time = 300;//一张图片位移总时间
             var inteval = 10;//位移间隔时间
             var speed = offset/(time/inteval);//求得一次位移的距离
             var newLeft = parseInt(list.style.left) + offset;//图片左侧距离父元素的值
    
            //动画函数
             var go = function (){
            //监测是否具备进行动画位移的条件
            //判断左切换和右切换两种情况,都并且一张图片没有完整的占满盒子区域时。
                 if ( (speed > 0 && parseInt(list.style.left) < newLeft) || (speed < 0 && parseInt(list.style.left) >newLeft)) {
                       list.style.left = parseInt(list.style.left) + speed + 'px';
                       setTimeout(go, inteval);//递归
                  }else {
                        list.style.left = newLeft + 'px';
                        if(newLeft>-600){
                            list.style.left=-3000+'px';//归位到第五张图片
                         }
                        if(newLeft<-3000){
                        list.style.left=-600+'px';//归位到第一张图片
                        }
                        // debugger;
                        animated = false;//结束动画位移
                 }
              }
            go();//函数调用
       }
    

    优化:加入下面代码,当传入的偏移量为0时,animate()函数里面的部分不需再执行了。

      if (offset == 0) {
                        return;
        }
    

    按钮切换

    先设置初始值index的值为1.即默认第一个小圆点时点亮着的,index用来标识第几个小圆点。点击箭头时增加或者减小index的值来实现切换小圆点的功能。注意index的取值是1~5,所以当index的值加到5时,要回归到1;index的值为1时,要切到5.

    实现思路:先判断index的值,右箭头触发点击事件里如果当前index的值为5,就使index=1,否则index+=1;,同理,左箭头触发点击事件里如果当前index的值为1,就使index=5,否则index-=1;
    然后点亮相应的小圆点showButton()

        var index = 1;
        next.onclick=function(){
            animate(-600);
            if(index==5){
                index=1;//使index的值不超过5
            }else{
                index+=1;//index的值随着箭头的点击进行更新
            }
            showButton();
        }
    
        prev.onclick=function(){
            animate(600);   
            if(index==1){
                index=5;//使index的值不小于1
            }else{
                index-=1;
            }
            showButton();
    
        }
    

    优化:在两个点击事件中先加入以下代码。当检测到animated=true即进行着动画位移,不执行其他代码,避免卡顿优化性能。

    if (animated) {
             return;
      }
    

    获取小圆点var buttons = document.getElementById('buttons').getElementsByTagName('span');,不止一个,是一个数组类型。数组从0开始,所以index -1.
    因为css样式中#buttons .on{background: orangered;},所以这里利用className= 'on'来点亮小圆点。

    
        //点亮小圆点
        function showButton(){
            buttons[index -1].className = 'on';//点亮
        }
    

    这样会出现一个问题,切换到下一个小圆点时,前面点击过的小圆点依然是点亮着的。所有在showButton()函数中要先清除之前的样式。

    for(var i=0;i<buttons.length;i++){//遍历
                if(buttons[i].className=='on'){//关闭其他亮着的小圆点
                    buttons[i].className='';
                    // break;//一旦监测到就退出循环
                }
            }
    

    这样就实现了点击箭头切换图片时,对应的小圆点也跟着进行切换。

    ===
    下面实现点击小圆点时,图片切换的功能
    思路:仍然是利用图片偏移量进行切换,偏移值为-600乘以要点击的小圆点的index值减去当前小圆点的index值)

    因为要对每一个小圆点添加点击事件,先对其进行遍历。
    首先获取要点击的(目标)小圆点的自定义属性值parseInt(this.getAttribute('index')),即在html布局中span标签里index的属性。

    getAttribute()既可以获取自定义属性值也可以获取原本就存在的属性的值。

    不要忘记更新当前的index值index=myIndex;

        //点击小圆点进行切换图片
        for (var i = 0; i < buttons.length; i++) {
            buttons[i].onclick = function(){//对每个小圆点添加点击事件
            var myIndex = parseInt(this.getAttribute('index'));//获取要点击的小圆点的自定义index属性值
            console.log(myIndex);
            var offset = -600*(myIndex-index);//求偏移值
            animate(offset);
            index=myIndex;//更新到当前的index值
            showButton();
            }
            // debugger;
        }
    
    

    优化:在每个小圆点的点击事件中加入以下代码。

    点击小圆点时,当检测到animated=true即进行动画位移的过程中,不触发该点击事件即不执行后面代码,避免卡顿优化性能。

    当检测到this.className=='on'即点击当前的小圆点,也不需要执行后面代码,优化性能。

    if (animated) {
         return;
     }
    if(this.className=='on'){
         return;    
     }  
    

    自动播放

    利用定时器setTimeout()setInterval,实现每隔3秒自动播放下一张图片。并在鼠标移到var container = document.getElementById('container');上时清楚浮动。

    用到一种回调函数的使用方式,如果stop(),stop方法就被执行了,但是如果写方法名stop,是事件触发时才会调用stop方法

    var interval = 3000;
    var timer;
    function play() {
            timer = setTimeout(function () {
                  next.onclick();
                  play();
            }, interval); 
    }
    function stop() {
            clearTimeout(timer);
     }
    /*
        //每隔3秒自动播放下一张图片
        function play(){
            timer = setInterval(function(){
                next.onclick();
            },3000);
        }
        //清除定时器
        function stop(){
            clearInterval(timer);
        }
    */
    
    container.onmouseover = stop;
    container.onmouseout = play;
    play();
    

    最后,如果不进行一些优化,可能会出现疯狂点击会使图片错位等情况。

    相关文章

      网友评论

          本文标题:使用JavaScript实现图片轮播效果

          本文链接:https://www.haomeiwen.com/subject/sgxxhxtx.html