滑动展示效果主要用在图片或信息的滑动展示,也可以设置一下做成简单的口风琴(Accordion)效果。这个其实就是以前写的图片滑动展示效果的改进版,那是我第一篇比较受关注的文章,是时候整理一下了。有如下特色:1,有四种方向模式选择;2,结合tween算法实现多种滑动效果;3,能自动根据滑动元素计算展示尺寸;4,也可自定义展示或收缩尺寸;5,可扩展自动切换功能;6,可扩展滑动提示功能。兼容:ie6/7/8, firefox 3.6.8, opera 10.51, safari 4.0.5, chrome 5.0
效果预览
0 0 1 1 2 2 3 3 4 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函数是这样的:
代码 var CLOSE = $$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方法。
【滑动对象】
程序初始化时会根据滑动元素创建滑动对象集合。先获取滑动元素:
var nodes = opt.nodes ? $$A.map( opt.nodes, function(n) { return n; } ) : $$A.filter( container.childNodes, function(n) { return n.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(){ return max; };getMin = function(){ return min; };如果没有自定义max或min,就根据元素尺寸来计算:
getMax = function(o){ return Math.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展示函数:
代码 var node = 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目标值函数:
var nodeShow = nodes[ index ], min = nodeShow.min, max = nodeShow.max;getTarget = function(o, i){ return i <= 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) { return this .tween( this ._time, o.begin, o.change, this .duration );});利用tween算法,结合当前时间,开始值,改变值和持续时间,就能得到当前要移动的坐标值。ps:关于tween缓动可以参考tween算法及缓动效果。
当_time到达duration说明滑动已经完成,再执行一次_targetMove目标值移动函数:
this ._setPos( function(o) { return o.target; } );直接移动到目标值,可以防止可能出现的计算误差导致移位不准确。
【关闭和重置】
close方法可以关闭展示,即滑动到默认状态,默认在移出容器时就会执行。默认状态是指全部滑动元素位于defaultTarget默认目标值的状态。先用_setMove设置移动参数,当_setMove没有索引参数时,就会设置目标值为默认目标值:
getTarget = function(o){ return o.defaultTarget; }完成参数设置后,再执行_easeMove进行滑动,跟滑动展示类似。
reset方法可以重置展示,重置的意思是不进行滑动而直接移动到目标值。如果没有索引参数,就会直接执行_defaultMove默认值移动函数:
this ._setPos( function(o) { return o.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指定的坐标样式来设置坐标值:
var pos = 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 有两种方法,可以调整元素插入顺序: < div class = " container " > < div style = " right:0; " > 2 < / div> < div style = " right:100px; " > 1 < / div> < div style = " right:200px; " > 0 < / div> < / div>但这样需要修改dom结构,或者通过zIndex设置堆叠顺序:
< div class = " container " > < div style = " right:200px;z-index:3; " > 0 < / div> < div style = " right:100px;z-index:2; " > 1 < / div> < div style = " right:0;z-index:1; " > 2 < / div> < / div>显然设置zIndex的方法比较好,程序也用了这个方法。程序就是用_reverse属性来判断是否需要做这些修正。
首先在_initContainer中,根据_reverse重新设置zIndex:
var zIndex = 100 , gradient = this ._reverse ? - 1 : 1 ; this ._each( function (o){ var style = o.node.style; style.position = " absolute " ; style.zIndex = zIndex += gradient;});在_initNodes中,获取默认目标值时也要判断:
getDefaultTarget = this ._reverse ? function(i){ return defaultSize * ( maxIndex - i ); } : function(i){ return defaultSize * i; },当_reverse为true时,由于定点位置是在索引的反方向,设置元素时也应该倒过来设的,所以要用maxIndex减一下。
在_setMove中,根据索引设置滑动目标值时,也要判断:
if ( this ._reverse ) { var get = getTarget; index = maxIndex - index; getTarget = function(o, i){ return get ( 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"定义一个能根据滑动元素获取提示元素的函数:
代码 var opt = this .options, tipTag = opt.tipTag, tipClass = opt.tipClass, re = tipClass && new RegExp( " (^|\\s) " + tipClass + " (\\s|$) " ), getTipNode = function(node){ var nodes = node.getElementsByTagName( tipTag ); if ( tipClass ) { nodes = $$A.filter( nodes, function(n){ return re.test(n.className); } ); } return nodes[ 0 ]; };如果自定义了tipTag,就会根据标签来获取元素,否则就按默认值"*"获取全部元素。如果自定义了tipClass,就会再根据className来筛选元素,注意可能包含多个样式,不能直接等于。
得到函数后,再创建提示对象:
代码 this ._each( function(o) { var node = 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"中设置提示移动目标值:
代码 var maxIndex = this ._nodes.length - 1 ; this ._each( function(o, i) { var tip = 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方法:
var pos = this ._tipPos; this ._each( function(o, i) { var tip = 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作为参数:
new SlideView( " 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//关闭时目标坐标
程序源码
代码 var SlideView = function (container, options){ this ._initialize( container, options ); this ._initContainer(); this ._initNodes(); this .reset( this .options.defaultIndex );};SlideView.prototype = { // 初始化程序 _initialize: function (container, options) { var container = this ._container = $$(container); // 容器对象 this ._timerDelay = null ; // 延迟计时器 this ._timerMove = null ; // 移动计时器 this ._time = 0 ; // 时间 this ._index = 0 ; // 索引 var opt = 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; // 设置参数 var pos = 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 ); // 获取滑动元素 var nodes = opt.nodes ? $$A.map( opt.nodes, function (n) { return n; } ) : $$A.filter( container.childNodes, function (n) { return n.nodeType == 1 ; }); // 创建滑动对象集合 this ._nodes = $$A.map( nodes, function (node){ var style = node.style; return { " node " : node, " style " : style[pos], " position " : style.position, " zIndex " : style.zIndex }; }); // 设置程序 this ._MOVE = $$F.bind( this ._move, this ); var CLOSE = $$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 = { // 默认值 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 () { // 容器样式设置 var container = 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 ); // 设置滑动元素 var zIndex = 100 , gradient = this ._reverse ? - 1 : 1 ; this ._each( function (o){ var style = o.node.style; style.position = " absolute " ; style.zIndex = zIndex += gradient; }); $$CE.fireEvent( this , " initContainer " ); }, // 设置滑动对象 _initNodes: function () { var len = 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){ return defaultSize * ( maxIndex - i ); } : function (i){ return defaultSize * 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 (){ return max; }; getMin = function (){ return min; }; } else { // 根据元素尺寸设置参数值 getMax = function (o){ return Math.max( Math.min( o.node[ offset ], clientSize ), defaultSize ); }; getMin = function (o){ return ( clientSize - o.max ) / maxIndex; }; } // 设置滑动对象 this ._each( function (o, i){ // 移入滑动元素时执行程序 var node = 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) { var setTarget; // 设置目标值函数 if ( index == undefined ) { // 设置默认状态目标值 getTarget = function (o){ return o.defaultTarget; } } else { // 根据索引设置滑动目标值 var nodes = this ._nodes, maxIndex = nodes.length - 1 ; // 设置索引 this ._index = index = index < 0 || index > maxIndex ? 0 : index | 0 ; // 设置展示参数 var nodeShow = nodes[ index ], min = nodeShow.min, max = nodeShow.max; getTarget = function (o, i){ return i <= index ? min * i : min * ( i - 1 ) + max; }; if ( this ._reverse ) { var get = getTarget; index = maxIndex - index; getTarget = function (o, i){ return get( 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) { return this .tween( this ._time, o.begin, o.change, this .duration ); }); $$CE.fireEvent( this , " tweenMove " ); }, // 目标值移动函数 _targetMove: function () { this ._setPos( function (o) { return o.target; } ); $$CE.fireEvent( this , " targetMove " ); }, // 默认值移动函数 _defaultMove: function () { this ._setPos( function (o) { return o.defaultTarget; } ); $$CE.fireEvent( this , " defaultMove " ); }, // 设置坐标值 _setPos: function (method) { clearTimeout( this ._timerMove); var pos = 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 " ); var pos = this ._pos; this ._each( function (o) { var style = 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 (){ var init = 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(); } }; return function (){ var options = 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 (){ var init = SlideView.prototype._initialize, methods = { " init " : function (){ // 坐标样式 this ._tipPos = / ^(bottom|top|right|left)$ / .test( this .options.tipPos.toLowerCase() ) ? RegExp.$ 1 : " bottom " ; }, " initNodes " : function (){ var opt = this .options, tipTag = opt.tipTag, tipClass = opt.tipClass, re = tipClass && new RegExp( " (^|\\s) " + tipClass + " (\\s|$) " ), getTipNode = function (node){ var nodes = node.getElementsByTagName( tipTag ); if ( tipClass ) { nodes = $$A.filter( nodes, function (n){ return re.test(n.className); } ); } return nodes[ 0 ]; }; // 设置提示对象 var tipShow = opt.tipShow, tipClose = opt.tipClose, offset = / right|left / .test( this ._tipPos ) ? " offsetWidth " : " offsetHeight " ; this ._each( function (o) { var node = 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){ var maxIndex = this ._nodes.length - 1 ; this ._each( function (o, i) { var tip = 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) { return Math.round( this .tween( this ._time, tip.begin, tip.change, this .duration ) ); }); }, " targetMove " : function (){ this ._setTipPos( function (tip){ return tip.target; }); }, " defaultMove " : function (){ this ._setTipPos( function (tip){ return tip.close; }); }, " dispose " : function (){ this ._each( function (o){ o.tip = null ; }); } }, prototype = { // 设置坐标值函数 _setTipPos: function (method) { var pos = this ._tipPos; this ._each( function (o, i) { var tip = o.tip; tip.node.style[ pos ] = (tip.current = method.call( this , tip )) + " px " ; }); } }; return function (){ var options = 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 ); }})();
完整实例下载
转载于:https://www.cnblogs.com/cloudgamer/archive/2010/07/29/SlideView.html
相关资源:数据结构—成绩单生成器