实现原理解读
使用两层for循环实现, 第一层有三个功能,分别给第个li: 添加索引 预设位置 添加事件 第二层有两个功能,整理图片位置: 鼠标的li,以及前面那些li的位置 鼠标后面那些li的位置
HTML/CSS 解读:略
HTML/CSS代码:
<!-- Author: XiaoWen Create a file: 2016-12-14 09:41:11 Last modified: 2016-12-15 12:56:23 Start 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>
实现原理的代码分析
两个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: XiaoWen Create a file: 2016-12-14 09:41:11 Last modified: 2016-12-15 13:23:08 Start 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>
附: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] } }
时间: 2024-10-07 22:08:40