幻灯片效果及原理
时间: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,等有时间修正下!!










