使用JavaScript实现图片轮播效果

原理

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

样式布局

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

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

![](img/5.jpg) ![](img/1.jpg) ![](img/2.jpg) ![](img/3.jpg) ![](img/4.jpg) ![](img/5.jpg) ![](img/1.jpg)

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

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

===
下面实现点击小圆点时,图片切换的功能
思路:仍然是利用图片偏移量进行切换,偏移值为-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实现图片轮播效果)