滑动展示效果主要用在图片或信息的滑动展示,也可以设置一下做成简单的口风琴(Accordion)效果。这个其实就是以前写的图片滑动展示效果的改进版,那是我第一篇比较受关注的文章,是时候整理一下了。
有如下特色:
有四种方向模式选择;结合tween算法实现多种滑动效果;能自动根据滑动元素计算展示尺寸;也可自定义展示或收缩尺寸;可扩展自动切换功能;可扩展滑动提示功能。
兼容:ie6/7/8, firefox 3.6.8, opera 10.51, safari 4.0.5, chrome 5.0
效果预览
0 01 12 23 34 4
模式:
左边右边
默认索引:
无01234
尺寸:
按元素尺寸展示占一半展示200px收缩占十分一收缩80px
关闭:
自动不自动
速度:
默认快速慢速
tween:
默认反弹
图片滑动展示效果:
内裤蛋糕 神秘浪漫的内裤蛋糕礼盒 内裤蛋糕 送给最亲密的TA~~ 内裤蛋糕 超SWEET~~打开漂亮的礼品盒,甜蜜可爱的蛋糕呈现眼前 内裤蛋糕 好Q哦!慢慢解开丝带,竟然是一条条漂亮的内裤 内裤蛋糕 超级SWEET又脸红耶!!!
仿口风琴(Accordion)效果:
图片放大效果这个效果也叫放大镜效果,最早好像在ppg出现的,之后就有了很多仿制品出来了。好处是能在原图附近对图片进行局部放大查看,而且可以通过鼠标控制查看的部位。 查看全文 Lazyload 延迟加载效果Lazyload是通过延迟加载来实现按需加载,达到节省资源,加快浏览速度的目的。网上也有不少类似的效果。 查看全文 图片上传预览效果图片上传预览是一种在图片上传之前对图片进行本地预览的技术。使用户选择图片后能立即查看图片,而不需上传服务器,提高用户体验。 查看全文 Tween算法及缓动效果Flash做动画时会用到Tween类,利用它可以做很多动画效果,例如缓动、弹簧等等。我这里要教大家的是怎么利用flash的Tween类的算法,来做js的Tween算法。 查看全文 Table行定位效果近来有客户要求用table显示一大串数据,由于滚动后就看不到表头,很不方便,所以想到这个效果。 查看全文
程序说明
【基本原理】
通过设置滑动元素的位置坐标(left/right/top/bottom),实现鼠标进入的目标元素滑动展示,其他元素滑动收缩的效果。
难点是如何控制多个滑动元素同时进行不同的滑动,这里关键就在于把整体滑动分解成各个滑动元素进行各自的滑动。
方法是给各个滑动元素设置目标值,然后各自向自己的目标值滑动,当全部都到达目标值就完成了。
【容器设置】
在_initContainer方法中进行容器设置,由于后面滑动参数的计算要用到容器,所以要先设置容器。
先设置容器样式,要实现滑动需要设置容器相对或绝对定位,并且设置overflow为"hidden"来固定容器大小,而滑动元素也要设置绝对定位。
鼠标移出容器时会触发_LEAVE移出函数:
$$E.addEvent(container,"mouseleave",this._LEAVE);
其中_LEAVE函数是这样的:
代码 varCLOSE=$$F.bind(this.close,this);
this._LEAVE=$$F.bind(function(){
clearTimeout(this._timerDelay);
$$CE.fireEvent(this,"leave");
if(this.autoClose){this._timerDelay=setTimeout(CLOSE,this.delay);}
},this);
当autoClose属性为true时才会延时触发close方法。
【滑动对象】
程序初始化时会根据滑动元素创建滑动对象集合。
先获取滑动元素:
varnodes=opt.nodes?$$A.map(opt.nodes,function(n){returnn;})
:$$A.filter(container.childNodes,function(n){returnn.nodeType==1;});
如果没有自定义nodes滑动元素,就从容器获取childNodes作为滑动元素。
还要用nodeType筛选一下,因为ie外的浏览器都会把空格作为childNodes的一部分。
接着用获取的滑动元素生成程序需要的_nodes滑动对象集合:
this._nodes=$$A.map(nodes,function(node){return{"node":node};});
滑动对象用"node"属性记录滑动元素。
然后在_initNodes方法中初始化滑动对象。
每个滑动对象都有3个用来计算滑动目标值的属性:defaultTarget默认目标值,max展示尺寸,min收缩尺寸。
如果有自定义max尺寸或min尺寸,会根据自定义的尺寸来计算。
程序会优先按max来计算:
max=Math.max(max<=1?max*clientSize:Math.min(max,clientSize),defaultSize);
min=(clientSize-max)/maxIndex;
其中clientSize是容器的可见区域尺寸,defaultSize是平均分配尺寸。
如果max是小数或1就按百分比计算,再把尺寸限制在defaultSize到clientSize的范围内。
再计算减去max后其他收缩元素的平均尺寸,就可以得到min了。
如果没有自定义max再按自定义min来计算:
min=Math.min(min<1?min*clientSize:min,defaultSize);
max=clientSize-maxIndex*min;
同样,如果min是小数就按百分比计算,再做范围限制,然后计算得出max。
最后得到自定义尺寸计算函数:
getMax=function(){returnmax;};
getMin=function(){returnmin;};
如果没有自定义max或min,就根据元素尺寸来计算:
getMax=function(o){returnMath.max(Math.min(o.node[offset],clientSize),defaultSize);};
getMin=function(o){return(clientSize-o.max)/maxIndex;};
把元素尺寸作为展示尺寸来计算,同样要做范围限制,然后计算收缩尺寸。
得到尺寸计算函数后,再用_each方法历遍并设置滑动对象:
o.current=o.defaultTarget=getDefaultTarget(i);
o.max=getMax(o);o.min=getMin(o);
其中current是当前坐标值,在移动计算时作为开始值的。
而defaultTarget是默认目标值,即默认状态时移动的目标值,根据defaultSize和索引得到。
还要设置当鼠标进入滑动元素时触发show展示函数:
代码 varnode=o.node,SHOW=$$F.bind(this.show,this,i);
o.SHOW=$$F.bind(function(){
clearTimeout(this._timerDelay);
this._timerDelay=setTimeout(SHOW,this.delay);
$$CE.fireEvent(this,"enter",i);
},this);
$$E.addEvent(node,"mouseenter",o.SHOW);
要在滑动元素的"mouseenter"事件中触发,并传递当前滑动对象的索引,再加上延时设置就可以了。
【滑动展示】
当鼠标进入其中一个滑动元素,就会触发show方法开始展示。
首先执行_setMove方法设置滑动参数,并以索引作为参数。
在_setMove里面主要是设置计算移动值时需要的目标值、开始值和变化值。
先修正索引,错误的索引值会设置为0:
this._index=index=index<0||index>maxIndex?0:index|0;
再根据索引获取要展示的滑动对象,通过展示对象的min和max得到getTarget目标值函数:
varnodeShow=nodes[index],min=nodeShow.min,max=nodeShow.max;
getTarget=function(o,i){returni<=index?min*i:min*(i-1)+max;};
如果滑动对象就是展示对象或者在展示对象前面,目标值就是min * i,因为第i+1个滑动对象的目标值就是i个min的大小。
否则,目标值就是min * ( i - 1 ) + max,其实就是把展示对象的位置换成max。
然后设置每个滑动对象的参数属性:
this._each(function(o,i){
o.target=getTarget(o,i);
o.begin=o.current;
o.change=o.target-o.begin;
});
其中target记录目标值,begin通过current得到开始值,目标值和开始值的差就是change改变值。
设置完成后,就执行_easeMove方法开始滑移,在里面重置_time属性为0,再就执行_move程序就正式开始移动了。
首先判断_time是否到达duration持续时间,没有到达的话,就继续移动。
程序设置了一个_tweenMove移动函数,用来设置缓动:
this._setPos(function(o){
returnthis.tween(this._time,o.begin,o.change,this.duration);
});
利用tween算法,结合当前时间,开始值,改变值和持续时间,就能得到当前要移动的坐标值。
ps:关于tween缓动可以参考tween算法及缓动效果。
当_time到达duration说明滑动已经完成,再执行一次_targetMove目标值移动函数:
this._setPos(function(o){returno.target;});
直接移动到目标值,可以防止可能出现的计算误差导致移位不准确。
【关闭和重置】
close方法可以关闭展示,即滑动到默认状态,默认在移出容器时就会执行。
默认状态是指全部滑动元素位于defaultTarget默认目标值的状态。
先用_setMove设置移动参数,当_setMove没有索引参数时,就会设置目标值为默认目标值:
getTarget=function(o){returno.defaultTarget;}
完成参数设置后,再执行_easeMove进行滑动,跟滑动展示类似。
reset方法可以重置展示,重置的意思是不进行滑动而直接移动到目标值。
如果没有索引参数,就会直接执行_defaultMove默认值移动函数:
this._setPos(function(o){returno.defaultTarget;});
直接把滑动元素移动到默认状态。
如果有索引参数,就先用_setMove根据索引设置目标值,再执行_targetMove直接移动到目标值。
程序初始化后会执行一次reset,并且以自定义defaultIndex作为参数。
利用defaultIndex可以一开始就展示对应索引的滑动对象。
【方向模式】
程序可以自定义mode方向模式,有四种方向模式:bottom、top、right、left(默认)。
其中right和left是在水平方向滑动,而bottom和top是在垂直方向滑动。
而right和left的区别是定点方向不同,left以左边为定点在右边滑动,right就相反。
具体参考实例就应该明白了,bottom和top的区别也类似。
程序是通过对不同的方向就修改对应方向的坐标样式来实现的。
例如left模式就用"left"样式来做移动效果,top模式就用"top"样式。
初始化程序中设置的_pos属性就是用来记录当前模式要使用的坐标样式的:
this._pos=/^(bottom|top|right|left)$/.test(opt.mode.toLowerCase())?RegExp.$1:"left";
然后在_setPos方法中使用_pos指定的坐标样式来设置坐标值:
varpos=this._pos;
this._each(function(o,i){
o.node.style[pos]=(o.current=Math.round(method.call(this,o)))+"px";
});
而_horizontal属性就记录了是否水平方向滑动,即是否right或left。
在计算尺寸时,通过它来指定使用用水平还是垂直方向的尺寸。
还有一个_reverse属性,判断是否bottom或right模式。
这个属性是为了解决一个问题,例如right模式要实现类似下面的效果:
2 1 0
有两种方法,可以调整元素插入顺序:
<divclass="container">
<divstyle="right:0;">2</div>
<divstyle="right:100px;">1</div>
<divstyle="right:200px;">0</div>
</div>
但这样需要修改dom结构,或者通过zIndex设置堆叠顺序:
<divclass="container">
<divstyle="right:200px;z-index:3;">0</div>
<divstyle="right:100px;z-index:2;">1</div>
<divstyle="right:0;z-index:1;">2</div>
</div>
显然设置zIndex的方法比较好,程序也用了这个方法。
程序就是用_reverse属性来判断是否需要做这些修正。
首先在_initContainer中,根据_reverse重新设置zIndex:
varzIndex=100,gradient=this._reverse?-1:1;
this._each(function(o){
varstyle=o.node.style;
style.position="absolute";style.zIndex=zIndex+=gradient;
});
在_initNodes中,获取默认目标值时也要判断:
getDefaultTarget=this._reverse
?function(i){returndefaultSize*(maxIndex-i);}
:function(i){returndefaultSize*i;},
当_reverse为true时,由于定点位置是在索引的反方向,设置元素时也应该倒过来设的,所以要用maxIndex减一下。
在_setMove中,根据索引设置滑动目标值时,也要判断:
if(this._reverse){
varget=getTarget;
index=maxIndex-index;
getTarget=function(o,i){returnget(o,maxIndex-i);}
}
不但滑动对象集合的索引要修正,展示对象的索引也要修正。
【自动展示扩展】
这次扩展用的是组合模式,原理参考的ImageZoom扩展篇的扩展模式部分。
不同的是加了一个属性扩展,用来添加扩展方法:
$$.extend(this,prototype);
注意不能添加到SlideView.prototype,这样会影响到SlideView的结构。
“自动展示”要实现的是滑动对象自动轮流展示,并且取消默认状态而实行强制展示,可以用在图片的轮换展示。
只要在SlideView后面加入自动展示扩展程序,并且auto参数设为true就会启用。
原理也很简单,就是每次滑动/移动完成后,用定时器执行下一次滑动就行了。
首先在"init"初始化程序中,增加一个_NEXT程序,用来展示下一个滑动对象:
this._NEXT=$$F.bind(function(){this.show(this._index+1);},this);
其实就是把当前索引_index加1之后作为show的参数执行。
再增加一个_autoNext方法:
if(!this._autoPause){
clearTimeout(this._autoTimer);
this._autoTimer=setTimeout(this._NEXT,this.autoDelay);
}
作用是延时执行_NEXT程序,并且有一个_autoPause属性用来锁定执行。
然后设置几个需要执行的地方。
首先在"finish"完成滑动事件中,执行_autoNext方法,这样就实现了基本的自动展示了。
在鼠标进入滑动元素后,应该停止自动切换,所以在"enter"进入滑动元素事件中,会清除定时器并把_autoPause设为true来锁定。
对应地在"leave"鼠标离开容器事件中,要把_autoPause设回false解除锁定,再执行_autoNext方法重新启动自动程序。
并且在"leave"中设置autoClose为false,防止自动恢复默认状态。
最后还要重写reset:
reset.call(this,index==undefined?this._index:index);
this._autoNext();
重写后的reset会强制设置索引来展示,并执行_autoNext进行下一次滑动。
【提示信息扩展】
“提示信息”效果是指每个滑动对象对应有一个提示信息(内容)的层(元素)。
这个提示信息会在滑动对象展示时展示,收缩和关闭时关闭。
只要加入提示信息扩展程序,并且tip参数设为true就会启用。
提示扩展支持四种位置提示:bottom、top、right、left。
在"init"中,根据自定义tipMode获取_tipPos坐标样式:
this._tipPos=/^(bottom|top|right|left)$/.test(this.options.tipPos.toLowerCase())?RegExp.$1:"bottom";
接着在"initNodes"定义一个能根据滑动元素获取提示元素的函数:
代码 varopt=this.options,tipTag=opt.tipTag,tipClass=opt.tipClass,
re=tipClass&&newRegExp("(^|\\s)"+tipClass+"(\\s|$)"),
getTipNode=function(node){
varnodes=node.getElementsByTagName(tipTag);
if(tipClass){
nodes=$$A.filter(nodes,function(n){returnre.test(n.className);});
}
returnnodes[0];
};
如果自定义了tipTag,就会根据标签来获取元素,否则就按默认值"*"获取全部元素。
如果自定义了tipClass,就会再根据className来筛选元素,注意可能包含多个样式,不能直接等于。
得到函数后,再创建提示对象:
代码 this._each(function(o){
varnode=o.node,tipNode=getTipNode(node);
node.style.overflow="hidden";
tipNode.style.position="absolute";tipNode.style.left=0;
o.tip={
"node":tipNode,
"show":tipShow!=undefined?tipShow:0,
"close":tipClose!=undefined?tipClose:-tipNode[offset]
};
});
先获取提示元素,并设置相关样式,再给滑动对象添加一个tip属性,保存对应的提示对象。
其中"node"属性保存提示元素,"show"是展示时的坐标值,"close"是关闭时的坐标值。
如果没有自定义tipShow,默认展示时坐标值是0,即提示元素刚好贴在滑动元素边上的位置;
如果没有自定义tipClose,默认关闭时坐标是提示元素的尺寸,即提示元素刚好隐藏在滑动元素外面的位置。
在"setMove"中设置提示移动目标值:
代码 varmaxIndex=this._nodes.length-1;
this._each(function(o,i){
vartip=o.tip;
if(this._reverse){i=maxIndex-i;}
tip.target=index==undefined||index!=i?tip.close:tip.show;
tip.begin=tip.current;tip.change=tip.target-tip.begin;
});
这个比滑动对象的设置简单得多,当设置了index参数,并且index等于该滑动对象的索引时才需要展示,其他情况都是隐藏。
要注意,跟滑动对象一样,在_reverse为true的时候需要修正索引。
在"tweenMove"、"targetMove"、"defaultMove"也要设置对应的移动函数。
为了方便样式设置,扩展了一个_setTipPos方法:
varpos=this._tipPos;
this._each(function(o,i){
vartip=o.tip;
tip.node.style[pos]=(tip.current=method.call(this,tip))+"px";
});
根据_tipPos坐标样式来设置坐标值。
使用技巧
【展示尺寸】
要自定义展示尺寸可以通过max和min来设置,可以按像素或百分比来计算。
如果不设置的话,就会按照元素本身的尺寸来展示。
所以滑动元素展示的尺寸并不需要一致的,程序可以自动计算。
【Accordion效果】
Accordion是可折叠的面板控件,效果类似手风琴,SlideView通过设置也能做到类似的效果。
首先把autoClose设为false取消自动关闭,再设置defaultIndex,使SlideView处于展开状态不会关闭。
一般Accordion都有一个固定尺寸的标题,这个可以用min来设置。
这样就实现了简单的Accordion效果,具体参考第三个实例。
使用说明
实例化时,必须有容器对象或id作为参数:
newSlideView("idSlideView");
可选参数用来设置系统的默认属性,包括:
属性: 默认值//说明
nodes:null,//自定义展示元素集合
mode:"left",//方向
max:0,//展示尺寸(像素或百分比)
min:0,//收缩尺寸(像素或百分比)
delay:100,//触发延时
interval:20,//滑动间隔
duration:20,//滑动持续时间
defaultIndex:null,//默认展示索引
autoClose:true,//是否自动恢复
tween:function(t,b,c,d){ return -c * ((t=t/d-1)*t*t*t - 1) + b; },//tween算子
onShow:function(index){},//滑动展示时执行
onClose:function(){}//滑动关闭执行
其中interval、delay、duration、tween、autoClose、onShow、onClose属性可以在程序初始化后动态设置。
还提供了以下方法:
show:根据索引滑动展示;
close:滑动到默认状态;
reset:重置为默认状态或展开索引对应滑动对象;
dispose:销毁程序。
要使用自动展示,只要在SlideView后面加入自动展示扩展程序,并且auto参数设为true即可。
新增如下可选参数:
autoDelay:2000//展示时间
要使用提示信息,只要加入提示信息扩展程序,并且tip参数设为true即可。
新增如下可选参数:
属性: 默认值//说明
tipPos:"bottom",//提示位置
tipTag:"*",//提示元素标签
tipClass:"",//提示元素样式
tipShow:null,//展示时目标坐标
tipClose:null//关闭时目标坐标
程序源码
代码 varSlideView=function(container,options){
this._initialize(container,options);
this._initContainer();
this._initNodes();
this.reset(this.options.defaultIndex);
};
SlideView.prototype={
//初始化程序
_initialize:function(container,options){
varcontainer=this._container=$$(container);//容器对象
this._timerDelay=null;//延迟计时器
this._timerMove=null;//移动计时器
this._time=0;//时间
this._index=0;//索引
varopt=this._setOptions(options);
this.interval=opt.interval|0;
this.delay=opt.delay|0;
this.duration=opt.duration|0;
this.tween=opt.tween;
this.autoClose=!!opt.autoClose;
this.onShow=opt.onShow;
this.onClose=opt.onClose;
//设置参数
varpos=this._pos=/^(bottom|top|right|left)$/.test(opt.mode.toLowerCase())?RegExp.$1:"left";
this._horizontal=/right|left/.test(this._pos);
this._reverse=/bottom|right/.test(this._pos);
//获取滑动元素
varnodes=opt.nodes?$$A.map(opt.nodes,function(n){returnn;})
:$$A.filter(container.childNodes,function(n){returnn.nodeType==1;});
//创建滑动对象集合
this._nodes=$$A.map(nodes,function(node){
varstyle=node.style;
return{"node":node,"style":style[pos],"position":style.position,"zIndex":style.zIndex};
});
//设置程序
this._MOVE=$$F.bind(this._move,this);
varCLOSE=$$F.bind(this.close,this);
this._LEAVE=$$F.bind(function(){
clearTimeout(this._timerDelay);
$$CE.fireEvent(this,"leave");
if(this.autoClose){this._timerDelay=setTimeout(CLOSE,this.delay);}
},this);
$$CE.fireEvent(this,"init");
},
//设置默认属性
_setOptions:function(options){
this.options=nbsp;{//默认值
nodes:null,//自定义展示元素集合
mode:"left",//方向
max:0,//展示尺寸(像素或百分比)
min:0,//收缩尺寸(像素或百分比)
delay:100,//触发延时
interval:20,//滑动间隔
duration:20,//滑动持续时间
defaultIndex:null,//默认展示索引
autoClose:true,//是否自动恢复
tween:function(t,b,c,d){return-c*((t=t/d-1)*t*t*t-1)+b;},//tween算子
onShow:function(index){},//滑动展示时执行
onClose:function(){}//滑动关闭执行
};
return$$.extend(this.options,options||{});
},
//设置容器
_initContainer:function(){
//容器样式设置
varcontainer=this._container,style=container.style,position=$$D.getStyle(container,"position");
this._style={"position":style.position,"overflow":style.overflow};//备份样式
if(position!="relative"&&position!="absolute"){style.position="relative";}
style.overflow="hidden";
//移出容器时
$$E.addEvent(container,"mouseleave",this._LEAVE);
//设置滑动元素
varzIndex=100,gradient=this._reverse?-1:1;
this._each(function(o){
varstyle=o.node.style;
style.position="absolute";style.zIndex=zIndex+=gradient;
});
$$CE.fireEvent(this,"initContainer");
},
//设置滑动对象
_initNodes:function(){
varlen=this._nodes.length,maxIndex=len-1,
type=this._horizontal?"Width":"Height",offset="offset"+type,
clientSize=this._container["client"+type],
defaultSize=Math.round(clientSize/len),
//计算默认目标值的函数
getDefaultTarget=this._reverse
?function(i){returndefaultSize*(maxIndex-i);}
:function(i){returndefaultSize*i;},
max=this.options.max,min=this.options.min,getMax,getMin;
//设置参数函数
if(max>0||min>0){//自定义参数值
//小数按百分比设置
if(max>0){
max=Math.max(max<=1?max*clientSize:Math.min(max,clientSize),defaultSize);
min=(clientSize-max)/maxIndex;
}else{
min=Math.min(min<1?min*clientSize:min,defaultSize);
max=clientSize-maxIndex*min;
}
getMax=function(){returnmax;};
getMin=function(){returnmin;};
}else{//根据元素尺寸设置参数值
getMax=function(o){returnMath.max(Math.min(o.node[offset],clientSize),defaultSize);};
getMin=function(o){return(clientSize-o.max)/maxIndex;};
}
//设置滑动对象
this._each(function(o,i){
//移入滑动元素时执行程序
varnode=o.node,SHOW=$$F.bind(this.show,this,i);
o.SHOW=$$F.bind(function(){
clearTimeout(this._timerDelay);
this._timerDelay=setTimeout(SHOW,this.delay);
$$CE.fireEvent(this,"enter",i);
},this);
$$E.addEvent(node,"mouseenter",o.SHOW);
//计算尺寸
o.current=o.defaultTarget=getDefaultTarget(i);//默认目标值
o.max=getMax(o);o.min=getMin(o);
});
$$CE.fireEvent(this,"initNodes");
},
//根据索引滑动展示
show:function(index){
this._setMove(index|0);
this.onShow(this._index);
this._easeMove();
},
//滑动到默认状态
close:function(){
this._setMove();
this.onClose();
this._easeMove();
},
//重置为默认状态或展开索引对应滑动对象
reset:function(index){
clearTimeout(this._timerDelay);
if(index==undefined){
this._defaultMove();
}else{
this._setMove(index);
this.onShow(this._index);
this._targetMove();
}
},
//设置滑动参数
_setMove:function(index){
varsetTarget;//设置目标值函数
if(index==undefined){//设置默认状态目标值
getTarget=function(o){returno.defaultTarget;}
}else{//根据索引设置滑动目标值
varnodes=this._nodes,maxIndex=nodes.length-1;
//设置索引
this._index=index=index<0||index>maxIndex?0:index|0;
//设置展示参数
varnodeShow=nodes[index],min=nodeShow.min,max=nodeShow.max;
getTarget=function(o,i){returni<=index?min*i:min*(i-1)+max;};
if(this._reverse){
varget=getTarget;
index=maxIndex-index;
getTarget=function(o,i){returnget(o,maxIndex-i);}
}
}
this._each(function(o,i){
o.target=getTarget(o,i);//设置目标值
o.begin=o.current;//设置开始值
o.change=o.target-o.begin;//设置变化值
});
$$CE.fireEvent(this,"setMove",index);
},
//滑移程序
_easeMove:function(){
this._time=0;this._move();
},
//移动程序
_move:function(){
if(this._time<this.duration){//未到达
this._tweenMove();
this._time++;
this._timerMove=setTimeout(this._MOVE,this.interval);
}else{//完成
this._targetMove();//防止计算误差
$$CE.fireEvent(this,"finish");
}
},
//tween移动函数
_tweenMove:function(){
this._setPos(function(o){
returnthis.tween(this._time,o.begin,o.change,this.duration);
});
$$CE.fireEvent(this,"tweenMove");
},
//目标值移动函数
_targetMove:function(){
this._setPos(function(o){returno.target;});
$$CE.fireEvent(this,"targetMove");
},
//默认值移动函数
_defaultMove:function(){
this._setPos(function(o){returno.defaultTarget;});
$$CE.fireEvent(this,"defaultMove");
},
//设置坐标值
_setPos:function(method){
clearTimeout(this._timerMove);
varpos=this._pos;
this._each(function(o,i){
o.node.style[pos]=(o.current=Math.round(method.call(this,o)))+"px";
});
},
//历遍滑动对象集合
_each:function(callback){
$$A.forEach(this._nodes,callback,this);
},
//销毁程序
dispose:function(){
clearTimeout(this._timerDelay);
clearTimeout(this._timerMove);
$$CE.fireEvent(this,"dispose");
varpos=this._pos;
this._each(function(o){
varstyle=o.node.style;
style[pos]=o.style;style.zIndex=o.zIndex;style.position=o.position;//恢复样式
$$E.removeEvent(o.node,"mouseenter",o.SHOW);o.SHOW=o.node=null;
});
$$E.removeEvent(this._container,"mouseleave",this._LEAVE);
$$D.setStyle(this._container,this._style);
this._container=this._nodes=this._MOVE=this._LEAVE=null;
$$CE.clearEvent(this);
}
};
自动展示扩展
代码 SlideView.prototype._initialize=(function(){
varinit=SlideView.prototype._initialize,
reset=SlideView.prototype.reset,
methods={
"init":function(){
this.autoDelay=this.options.autoDelay|0;
this._autoTimer=null;//定时器
this._autoPause=false;//暂停自动展示
//展示下一个滑动对象
this._NEXT=$$F.bind(function(){this.show(this._index+1);},this);
},
"leave":function(){
this.autoClose=this._autoPause=false;
this._autoNext();
},
"enter":function(){
clearTimeout(this._autoTimer);
this._autoPause=true;
},
"finish":function(){
this._autoNext();
},
"dispose":function(){
clearTimeout(this._autoTimer);
}
},
prototype={
_autoNext:function(){
if(!this._autoPause){
clearTimeout(this._autoTimer);
this._autoTimer=setTimeout(this._NEXT,this.autoDelay);
}
},
reset:function(index){
reset.call(this,index==undefined?this._index:index);
this._autoNext();
}
};
returnfunction(){
varoptions=arguments[1];
if(options&&options.auto){
//扩展options
$$.extend(options,{
autoDelay:2000//展示时间
},false);
//扩展属性
$$.extend(this,prototype);
//扩展钩子
$$A.forEach(methods,function(method,name){
$$CE.addEvent(this,name,method);
},this);
}
init.apply(this,arguments);
}
})();
提示信息扩展
代码 SlideView.prototype._initialize=(function(){
varinit=SlideView.prototype._initialize,
methods={
"init":function(){
//坐标样式
this._tipPos=/^(bottom|top|right|left)$/.test(this.options.tipPos.toLowerCase())?RegExp.$1:"bottom";
},
"initNodes":function(){
varopt=this.options,tipTag=opt.tipTag,tipClass=opt.tipClass,
re=tipClass&&newRegExp("(^|\\s)"+tipClass+"(\\s|$)"),
getTipNode=function(node){
varnodes=node.getElementsByTagName(tipTag);
if(tipClass){
nodes=$$A.filter(nodes,function(n){returnre.test(n.className);});
}
returnnodes[0];
};
//设置提示对象
vartipShow=opt.tipShow,tipClose=opt.tipClose,
offset=/right|left/.test(this._tipPos)?"offsetWidth":"offsetHeight";
this._each(function(o){
varnode=o.node,tipNode=getTipNode(node);
node.style.overflow="hidden";
tipNode.style.position="absolute";tipNode.style.left=0;
//创建提示对象
o.tip={
"node":tipNode,
"show":tipShow!=undefined?tipShow:0,
"close":tipClose!=undefined?tipClose:-tipNode[offset]
};
});
},
"setMove":function(index){
varmaxIndex=this._nodes.length-1;
this._each(function(o,i){
vartip=o.tip;
if(this._reverse){i=maxIndex-i;}
tip.target=index==undefined||index!=i?tip.close:tip.show;
tip.begin=tip.current;tip.change=tip.target-tip.begin;
});
},
"tweenMove":function(){
this._setTipPos(function(tip){
returnMath.round(this.tween(this._time,tip.begin,tip.change,this.duration));
});
},
"targetMove":function(){
this._setTipPos(function(tip){returntip.target;});
},
"defaultMove":function(){
this._setTipPos(function(tip){returntip.close;});
},
"dispose":function(){
this._each(function(o){o.tip=null;});
}
},
prototype={
//设置坐标值函数
_setTipPos:function(method){
varpos=this._tipPos;
this._each(function(o,i){
vartip=o.tip;
tip.node.style[pos]=(tip.current=method.call(this,tip))+"px";
});
}
};
returnfunction(){
varoptions=arguments[1];
if(options&&options.tip==true){
//扩展options
$$.extend(options,{
tipPos:"bottom",//提示位置
tipTag:"*",//提示元素标签
tipClass:"",//提示元素样式
tipShow:null,//展示时目标坐标
tipClose:null//关闭时目标坐标
},false);
//扩展属性
$$.extend(this,prototype);
//扩展钩子
$$A.forEach(methods,function(method,name){
$$CE.addEvent(this,name,method);
},this);
}
init.apply(this,arguments);
}
})();
完整实例下载
本文链接:/oooweb/p/javascript-slider-view.html
原文出处:coudgamer