首页 > 代码库 > js手风琴图片切换实现原理及函数分析

js手风琴图片切换实现原理及函数分析

技术分享

实现原理解读

  使用两层for循环实现,  第一层有三个功能,分别给第个li:    添加索引    预设位置    添加事件  第二层有两个功能,整理图片位置:    鼠标的li,以及前面那些li的位置    鼠标后面那些li的位置

HTML/CSS 解读:略

  HTML/CSS代码:
技术分享
<!--Author: XiaoWenCreate a file: 2016-12-14 09:41:11Last modified: 2016-12-15 12:56:23Start to work:Finish the work:Other information:--><!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>手风琴2</title>  <style>    *{      margin: 0;      padding: 0;    }    body{      background: #ccc;    }    div{      width: 1100px;      height: 300px;      margin: auto;      background: #ddd;      margin-top: 40px;      border-radius:10px;      border: 10px solid #fff;      box-shadow:0 0 20px #eee;    }    ul,li{      list-style:none;    }    img{      vertical-align: bottom;      width: 600px;      height: 300px;    }    ul{      position: relative;      overflow: hidden;      width: 1100px;      height: 300px;    }    ul li{      position: absolute;      width: 600px;      height: 300px;      overflow: hidden;    }  </style></head><body>  <div>    <ul>      <li><img src="1.jpg" alt="图片1"></li>      <li><img src="2.jpg" alt="图片2"></li>      <li><img src="3.jpg" alt="图片3"></li>      <li><img src="4.jpg" alt="图片4"></li>      <li><img src="5.jpg" alt="图片5"></li>      <li><img src="6.jpg" alt="图片6"></li>    </ul>  </div></body></html>
View Code

 

实现原理的代码分析

  两个for循环的js代码:  无分析的代码:
for(var i=0;i<aLi.length;i++){  aLi[i].index=i;  if(i!=0){    aLi[i].style.left=600+100*(i-1)+‘px‘;  }  aLi[i].onmouseover=function(){    for(var j=0;j<aLi.length;j++){      if(j<=this.index){        move(aLi[j],‘left‘,100*j)      }else{        move(aLi[j],‘left‘,600+100*(j-1))      }    }  }}
  有分析的代码:
for(var i=0;i<aLi.length;i++){  //给每个li添加自定义属性 index ,用来保存i供鼠标函数使用  aLi[i].index=i;  //预置图片位置  if(i!=0){    //其他图片位置,在第一张图片后面。    //第一张宽度+后面每张图片显示出来的距离*(后面图片的下标-1)。    //为什么-1    //因为第2张图离第1张图0单位距离,第3张离第1张1单位距离……    aLi[i].style.left=600+100*(i-1)+‘px‘;  }  //给每张图片添加鼠标移入事件  aLi[i].onmouseover=function(){    for(var j=0;j<aLi.length;j++){      //若鼠标在第1张图片上时      //第1次循环, j=0 ;index=0 ;j <= this.index  是;执行 move(aLi[0],‘left‘,100*0) ;第1张图片位置0不动      //第2次循环, j=1 ;index=0 ;j <= this.index  否;执行 move(aLi[1],‘left‘,600+100*(1-1)) ;第2张图片位置600不动      //第3次循环, j=2 ;index=0 ;j <= this.index  否;执行 move(aLi[2],‘left‘,600+100*(2-1)) ;第3张图片位置700不动      //直到循环完成,都不动...      //若鼠标在第2张图片上时      //第1次循环, j=0 ;index=1 ;j <= this.index  是;执行 move(aLi[0],‘left‘,100*0) ;第1张图片位置0不动      //第2次循环, j=1 ;index=1 ;j <= this.index  是;执行 move(aLi[1],‘left‘,100*1) ;第2张图片动,left从600变到100      //第3次循环, j=2 ;index=1 ;j <= this.index  否;执行 move(aLi[2],‘left‘,600+100*(2-1)) ;第3张图片位置700不动      //直到循环完成,都不动...      if(j<=this.index){        //鼠标所在图片前面那些图片的位置        move(aLi[j],‘left‘,100*j)      }else{        //鼠标所在图片后面那些图片的位置,j-1是为了规律100*0【1-1】,100*1【2-1】...的体现        //也就是后面的图片距离鼠标所在图片的位置倍数。        move(aLi[j],‘left‘,600+100*(j-1))      }    }  }}

单属性运动函数

  无分析的代码:
function move(obj,attr,iTarget){  clearInterval(obj.timer)  obj.timer=setInterval(function(){    var speed=(iTarget-parseInt(getStyle(obj,attr)))/10;    speed=speed>0 ? Math.ceil(speed) : Math.floor(speed);    if(iTarget==parseInt(getStyle(obj,attr))){      clearInterval(obj.timer);    }else{      obj.style[attr]=parseInt(getStyle(obj,attr))+speed+‘px‘;    }  },10)}

 

多属性运动函数

  有分析的代码:
function startMove(obj,json,fnEnd){  //每次调用时,需要只有一个定时器在工作,在开始运动时关闭所有定时器  //并且关闭或开启都是当前物体的定时器,防止与页面上其他定时器冲突,使每个定时器互不干扰  clearInterval(obj.timer);  obj.timer=setInterval(function(){    var bStop=true; //假设所有值都已经到达目标值    for(var name in json){      var iTarget=json[name]; //所有的目标值      if(name == ‘opacity‘){ // opacity 比较特殊,值是0到1之间        var cur=parseInt(parseFloat(getStyle(obj,name))*100); //转小数为整数,让下面的代码容易计算      }else{        var cur=parseInt(getStyle(obj,name)); //cur是物体当前数值      }      var speed=(iTarget-cur)/10; //整体的速度,数字越小运动越慢      speed=speed>0?Math.ceil(speed):Math.floor(speed);      if(name==‘opacity‘){        obj.style.opacity=(cur+speed)/100;      }else{        obj.style[name]=cur+speed+‘px‘; //除了opacity之外其他都需要px      };      //当某个值没有到目标值时      if(cur!=iTarget){        bStop=false;      };    };    if(bStop){      clearInterval(obj.timer);      //当前运动结束后的操作,也就是第三个参数      if(fnEnd){ //如果有这个参数,就执行        fnEnd();      }    }  },20)}

 

完整效果代码

技术分享
<!--Author: XiaoWenCreate a file: 2016-12-14 09:41:11Last modified: 2016-12-15 13:23:08Start to work:Finish the work:Other information:--><!DOCTYPE html><html lang="en"><head>  <meta charset="UTF-8">  <title>手风琴2</title>  <style>    *{      margin: 0;      padding: 0;    }    body{      background: #ccc;    }    div{      width: 1100px;      height: 300px;      margin: auto;      background: #ddd;      margin-top: 40px;      border-radius:10px;      border: 10px solid #fff;      box-shadow:0 0 20px #eee;    }    ul,li{      list-style:none;    }    img{      vertical-align: bottom;      width: 600px;      height: 300px;    }    ul{      position: relative;      overflow: hidden;      width: 1100px;      height: 300px;    }    ul li{      position: absolute;      width: 600px;      height: 300px;      overflow: hidden;    }  </style></head><body>  <div>    <ul>      <li><img src="1.jpg" alt="图片1"></li>      <li><img src="2.jpg" alt="图片2"></li>      <li><img src="3.jpg" alt="图片3"></li>      <li><img src="4.jpg" alt="图片4"></li>      <li><img src="5.jpg" alt="图片5"></li>      <li><img src="6.jpg" alt="图片6"></li>    </ul>  </div>  <script>  var aLi=document.getElementsByTagName(li);  for(var i=0;i<aLi.length;i++){    //给每个li添加自定义属性 index ,用来保存i供鼠标函数使用    aLi[i].index=i;    //预置图片位置    if(i!=0){      //其他图片位置,在第一张图片后面。      //第一张宽度+后面每张图片显示出来的距离*(后面图片的下标-1)。      //为什么-1      //因为第2张图离第1张图0单位距离,第3张离第1张1单位距离……      aLi[i].style.left=600+100*(i-1)+px;    }    //给每张图片添加鼠标移入事件    aLi[i].onmouseover=function(){      for(var j=0;j<aLi.length;j++){        //若鼠标在第1张图片上时        //第1次循环, j=0 ;index=0 ;j <= this.index  是;执行 move(aLi[0],‘left‘,100*0) ;第1张图片位置0不动        //第2次循环, j=1 ;index=0 ;j <= this.index  否;执行 move(aLi[1],‘left‘,600+100*(1-1)) ;第2张图片位置600不动        //第3次循环, j=2 ;index=0 ;j <= this.index  否;执行 move(aLi[2],‘left‘,600+100*(2-1)) ;第3张图片位置700不动        //直到循环完成,都不动...        //若鼠标在第2张图片上时        //第1次循环, j=0 ;index=1 ;j <= this.index  是;执行 move(aLi[0],‘left‘,100*0) ;第1张图片位置0不动        //第2次循环, j=1 ;index=1 ;j <= this.index  是;执行 move(aLi[1],‘left‘,100*1) ;第2张图片动,left从600变到100        //第3次循环, j=2 ;index=1 ;j <= this.index  否;执行 move(aLi[2],‘left‘,600+100*(2-1)) ;第3张图片位置700不动        //直到循环完成,都不动...        if(j<=this.index){          //鼠标所在图片前面那些图片的位置          move(aLi[j],left,100*j)        }else{          //鼠标所在图片后面那些图片的位置,j-1是为了规律100*0【1-1】,100*1【2-1】...的体现          //也就是后面的图片距离鼠标所在图片的位置倍数。          move(aLi[j],left,600+100*(j-1))        }      }    }  }  function getStyle(obj,attr){    if(obj.currentStyle){      return obj.currentStyle[attr]    }else{      return getComputedStyle(obj)[attr]    }  }  function move(obj,attr,iTarget){    clearInterval(obj.timer)    obj.timer=setInterval(function(){      var speed=(iTarget-parseInt(getStyle(obj,attr)))/10;      speed=speed>0 ? Math.ceil(speed) : Math.floor(speed);      if(iTarget==parseInt(getStyle(obj,attr))){        clearInterval(obj.timer);      }else{        obj.style[attr]=parseInt(getStyle(obj,attr))+speed+px;      }    },10)  }  function startMove(obj,json,fnEnd){    //每次调用时,需要只有一个定时器在工作,在开始运动时关闭所有定时器    //并且关闭或开启都是当前物体的定时器,防止与页面上其他定时器冲突,使每个定时器互不干扰    clearInterval(obj.timer);    obj.timer=setInterval(function(){      var bStop=true; //假设所有值都已经到达目标值      for(var name in json){        var iTarget=json[name]; //所有的目标值        if(name == opacity){ // opacity 比较特殊,值是0到1之间          var cur=parseInt(parseFloat(getStyle(obj,name))*100); //转小数为整数,让下面的代码容易计算        }else{          var cur=parseInt(getStyle(obj,name)); //cur是物体当前数值        }        var speed=(iTarget-cur)/10; //整体的速度,数字越小运动越慢        speed=speed>0?Math.ceil(speed):Math.floor(speed);        if(name==opacity){          obj.style.opacity=(cur+speed)/100;        }else{          obj.style[name]=cur+speed+px; //除了opacity之外其他都需要px        };        //当某个值没有到目标值时        if(cur!=iTarget){          bStop=false;        };      };      if(bStop){        clearInterval(obj.timer);        //当前运动结束后的操作,也就是第三个参数        if(fnEnd){ //如果有这个参数,就执行          fnEnd();        }      }    },20)  }  </script></body></html>
View Code

 

附:CSS值获取函数

  关于JS获取CSS值的研究请移步:
《JS获取元素CSS值的各种方法分析》
http://www.cnblogs.com/daysme/p/6117174.html
function getStyle(obj,attr){  if(obj.currentStyle){    return obj.currentStyle[attr]  }else{    return getComputedStyle(obj)[attr]  }}
    

js手风琴图片切换实现原理及函数分析