幻灯片效果及原理
时间:2011-04-26 来源:Matin
主要采用绝对定位的方法来实现,假设有10个元素要加入这个效果中;比如:点击按钮4,那么第4个张幻灯就要显示;分为curNum(当前的这张)和prevNum(前一张),通过比较curNum和prevNum的值来判断prevNum所对应的幻灯的定位,以便决定下一次它如何显示,而curNum和prevNum是通过对元素设定自定义属性得到;假设现在显示框现在显示的是第4张,而你想看第8张,点击了8,那么curNum=8,prevNum=4,因为prevNum<curNum,所以它被定位到显示框的左边,同时,把curNum赋值给prevNum,以便下一次判断;反之,如果prevNum>curNum,那就定位到显示框的右边;同理,curNum赋值给prevNum,以便下一次判断2者值的大小;
js幻灯片效果,实现起来的几个细节:
(1)如何解决自动播放和手动点击的计时器控制;
(2)表现层:css样式的设置;
(3)兼容性;
html层如下(只显示了其中的一部分,后面的就是ctrl+c,+v)的问题:
<div class="wrap"> <div id="slide"> <img id="loading" src="info-slide/loading.gif" alt="" /> <div > <a href="http://www.baidu.com" target="_blank"><img src='info-slide/1.jpg' alt='11eeeee' /></a> <h1>Image Number One</h1> <p>从一段距离,再到一段距离。星星寂寞的哭泣,让人大跌眼镜。就如此的用微光折射曲线,等候一种叫给予的怜悯。从现在开始,再不相信和理会月光的柔漫。从一个很远的距离遥望。爱情,却无法回到开始的距离。怪不得,缘在咫尺,却失之交臂千万别说在下一个轮回想见。你还是扮演来去无踪的绝美。我依然是我,禅钟下的凄凉,才是心和情的最终归属。千万不要费心的漫天撒花,草原的红狐狸依然掩面泣凄,绝对不要用你的柔情,逼我在红尘中一身白衣清醇的横空出世。绝美是你叹息后最好的掩饰,绝望是我叹息后最好的结局。怪不得,你袅袅的如烟-----望不可及.</p> <a href="http://www.cnblogs.com/zorroliu" target="_blank">更多...</a> </div> //这里就是要ctrl+c +v的地方,决定要加入多少个幻灯 ...... </div> </div>
css层如下:
这里面的position:absolute是很关键的一条代码;
#slide div {width:480px; position:absolute; left:500px; padding:10px;}
顺便提下这个图片替换技术:
#previous span ,#next span{display:none;}
#previous,#next{width:40px; position:absolute;top:150px; background:#990066;}
#previous{background:url(050.gif) no-repeat center;left:-5px; }
#next{background:url(051.gif) no-repeat center; right:-5px;}
用display:none;来隐藏当前文字,然后设定背景,当然,为了平稳退化的要求,一旦在其他终端设备上无法显示图片的时候,这种使用display:none的方法欠妥当,可以使用text-indent会更好一些;
完整的css:
body,div,ul,li,p,h1{ margin:0; padding:0;} .wrap{width:550px; border:5px solid #0099FF; position:relative; margin:0 auto;} #slide {width:500px;overflow:hidden;background:#fff;position:relative; margin:20px auto 0 auto; border:1px solid #999999} #slide div {width:480px; position:absolute; left:500px; padding:10px;} #slide div img {float:left; margin-right:10px; border:0;} #slide div h1 {color:#888; font-size:20px; font-family:"lucida sans", sans-serif; font-style:italic;} #slide div p ,#slide div a {font-family: Georgia, "Times New Roman", Times, serif, sans-serif; color:#444; line- font-size:12px;word-wrap:break-word;} #slide div a:hover {text-decoration:underline;} #previous span ,#next span{display:none;} #previous,#next{width:40px; position:absolute;top:150px; background:#990066;} #previous{background:url(050.gif) no-repeat center;left:-5px; } #next{background:url(051.gif) no-repeat center; right:-5px; } .handle_div {overflow:hidden;float:left; margin-left:100px;_display:inline; margin-top:5px;} .handle_div ul { float:left; list-style:none;} .handle_div ul li{width:22px;line- font-family:arial, sans-serif; font-size:12px;text-align:center;background: #CCCCCC;float:left;margin-right:5px; position:relative;} #loading {position:absolute; left:250px; top:120px;}
js如下:
定时器:采用了多个定时器,确实不是很好的方法,至少,看的不太舒服,不过了防止IE下过快点击产生的不良影响,我目前能想到的就是在鼠标事件中多次清理前面所绑定的计时器,采用“一刀切”的方法,切完之后,加一个新的计时器;
动画Tween:我只是用了一个比较简单的效果,可以用那个传给力的tween神器,里面有很多效果;
参数介绍:
effectEl:幻灯片显示框,具有ID的元素;
handle:幻灯片序号操作:具有ID的ul;
prevButton,nextButton:前后操作元素,具有ID的元素;
loadingImg:完全加载前的loading元素,具有ID的元素;
dir:自动播放时间间隔;
完整的js代码:
var $={ Id:function(el){ var doc=document; if(!el||el.nodeType==3||el.nodeType==4){return;} if(typeof el=="string"&&doc.getElementById){ return doc.getElementById(el); } if(el.nodeType==1){ return el; } }, child:function(tag,context){ var tags,len,tagArr=[]; if(!tag||!context||tag.nodeType==3||tag.nodeType==4){return;} if(typeof context==="string"){context=$.Id(context);}; context=context||document; if(context.getElementsByTagName&&context.nodeType===1){ if(typeof tag==="string"){ tags=context.getElementsByTagName(tag); len=tags.length; for(var i=0;i<len;i++){ if(tags[i].parentNode==context){ tagArr.push(tags[i]); } } return tagArr; } else if(tag.nodeType==1){return tag;} } return ; } }; var slide=function(effectEl,handle,prevButton,nextButton,loadingImg,dir){ var firstDiv,allshowDiv,len,allshowHandle,next=$.Id(nextButton),prev=$.Id(prevButton); effectEl=$.Id(effectEl); handle=$.Id(handle); loadingImg=$.Id(loadingImg); allshowHandle=$.child("li",handle); allshowDiv=$.child("div",effectEl); this.width=parseInt(!+"\v1"?effectEl.currentStyle["width"]:window.getComputedStyle(effectEl,null).getPropertyValue("width")); this.dir=dir; this._timerId=null; this.duration=dir||1500, this.init(allshowHandle,allshowDiv,loadingImg); this.cur(allshowHandle,allshowDiv,this.width,prev,next,this.animate) } slide.prototype={ init:function(allshowHandle,allshowDiv,loadingImg){ var len=allshowHandle.length,firstDiv=allshowDiv[0],handleNode,divNode; loadingImg.style.display="none"; firstDiv.style.left=0+"px"; for(var i=0;i<len;i++){ handleNode=allshowHandle[i],divNode=allshowDiv[i]; handleNode.setAttribute("id","handle_"+i); if(!divNode){divNode.innerHTML=="";} divNode.setAttribute("id","div_"+i); } }, cur:function(allshowHandle,allshowDiv,width,prevButton,nextButton){ var len=allshowHandle.length,prevNum=curNum=0,that=this; var access=function(){ prevNum=curNum; if(this.getAttribute("id")=="previous"){ curNum--; if(curNum<0){curNum=len-1}; that.animate(prevNum,curNum,allshowDiv,true); } else { curNum++; if(curNum>len-1){curNum=0}; that.animate(prevNum,curNum,allshowDiv,false); } that.cssOpea(allshowHandle,prevNum,curNum); that.stop(that._timerId); }; var timerFn=function(){ prevNum=curNum; curNum++; if(curNum>len-1){curNum=0}; that.cssOpea(allshowHandle,prevNum,curNum); that.animate(prevNum,curNum,allshowDiv,false); }; prevButton.onmousedown=nextButton.onmousedown=access; prevButton.onmouseup=nextButton.onmouseup=function(){ that.stop(that._timerId); that._timerId=that.setTimer(timerFn,that.duration) }; for(var i=0;i<len;i++){ ;(function(j){ allshowHandle[j].onmousedown=function(){ var getId=this.getAttribute("id").replace(/\D+/g,""); prevNum=curNum; curNum=getId; that.cssOpea(allshowHandle,prevNum,curNum); if(curNum>prevNum){ that.animate(prevNum,curNum,allshowDiv,false);} if(curNum<prevNum){ that.animate(prevNum,curNum,allshowDiv,true); } that.stop(that._timerId); }; allshowDiv[j].onmouseout=allshowHandle[j].onmouseup=function(){ that.stop(that._timerId); that._timerId=that.setTimer(timerFn,that.duration); }; allshowDiv[j].onmouseover= function(){ that.stop(that._timerId); }; })(i); } that._timerId=that.setTimer(timerFn,that.duration); }, animate:function(prevNum,curNum,allshowDiv,lr){ var that=this; var animateFn=function(obj){ var tween=function(position){ if ((position/=0.5) <1) return 0.5*Math.pow(position,3); return 0.5 * (Math.pow((position-2),3) +2); }; var duration=obj.duration, startPos=obj.start, target=obj.target, change=obj.changeProp, startTime=new Date().getTime(); setTimeout(function(){ var time=new Date().getTime(),nowTime=time-startTime; var process=Math.ceil(tween(nowTime/duration)*change); target.style.left=process+startPos+"px"; if(nowTime>=duration){ target.style.left=startPos+change+"px"; } else{ setTimeout(arguments.callee,10) } },10); } if(lr){ animateFn({target:allshowDiv[curNum],dir:that.dir,duration:500,start:-that.width,changeProp:that.width}) animateFn({target:allshowDiv[prevNum],dir:that.dir,duration:500,start:0,changeProp:that.width}) } else{ animateFn({target:allshowDiv[curNum],dir:that.dir,duration:500,start:that.width,changeProp:-that.width}) animateFn({target:allshowDiv[prevNum],dir:that.dir,duration:500,start:0,changeProp:-that.width}) } }, cssOpea:function(el,prevNum,curNum){ el[curNum].style.backgroundColor="#CC6633"; el[prevNum].style.backgroundColor="#CCCCCC"; }, stop:function(timerId){ clearInterval(timerId); }, setTimer:function(timerFn,timerduration){ var timerId=setInterval(timerFn,timerduration); return timerId; } } new slide("slide","buttons","previous","next","loading",3000);
这种类幻灯片有通用性,无非就是改改css什么的;当然,实现这个效果的方法有很多,比如计算offsetHeight来实现等等,框架版本的实现过段时间放上来;
兼容性:FF4.0,FF3.0+,IE 6/7/8,chrome,opera下有点bug,等有时间修正下!!