代码改变世界

幻灯片效果及原理

2011-04-26 17:56  Matin  阅读(1176)  评论(0)    收藏  举报

主要采用绝对定位的方法来实现,假设有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; height:280px; position:absolute; left:500px; padding:10px;}

顺便提下这个图片替换技术:

#previous span ,#next span{display:none;}
#previous,#next{width:40px; height: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; height:350px;border:5px solid  #0099FF; position:relative; margin:0 auto;}
#slide {width:500px;height:300px;overflow:hidden;background:#fff;position:relative; margin:20px auto 0 auto; border:1px solid #999999}
#slide div {width:480px; height:280px; 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-height:1.5em; font-size:12px;word-wrap:break-word;}
#slide div a:hover {text-decoration:underline;}
#previous span ,#next span{display:none;}
#previous,#next{width:40px; height: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-height:19px; font-family:arial, sans-serif; font-size:12px;text-align:center;background: #CCCCCC;float:left;margin-right:5px; height:19px; 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什么的;当然,实现这个效果的方法有很多,比如计算offsetWidth来实现等等,框架版本的实现过段时间放上来;

兼容性:FF4.0,FF3.0+,IE 6/7/8,chrome,opera下有点bug,等有时间修正下!!