天天看點

SlideView 圖檔滑動(擴充/收縮)展示效果

滑動展示效果主要用在圖檔或資訊的滑動展示,也可以設定一下做成簡單的口風琴(accordion)效果。

這個其實就是以前寫的圖檔滑動展示效果 的改進版,那是我第一篇比較受關注的文章,是時候整理一下了。

有如下特色:

1,有四種方向模式選擇;

3,能自動根據滑動元素計算展示尺寸;

4,也可自定義展示或收縮尺寸;

5,可擴充自動切換功能;

6,可擴充滑動提示功能。

相容:ie6/7/8, firefox 3.6.8, opera 10.51, safari 4.0.5, chrome 5.0

程式說明

【基本原理】

通過設定滑動元素的位置坐标(left/right/top/bottom),實作滑鼠進入的目标元素滑動展示,其他元素滑動收縮的效果。

難點是如何控制多個滑動元素同時進行不同的滑動,這裡關鍵就在于把整體滑動分解成各個滑動元素進行各自的滑動。

方法是給各個滑動元素設定目标值,然後各自向自己的目标值滑動,當全部都到達目标值就完成了。

【容器設定】

在_initcontainer方法中進行容器設定,由于後面滑動參數的計算要用到容器,是以要先設定容器。

先設定容器樣式,要實作滑動需要設定容器相對或絕對定位,并且設定overflow為"hidden"來固定容器大小,而滑動元素也要設定絕對定位。

滑鼠移出容器時會觸發_leave移出函數:

SlideView 圖檔滑動(擴充/收縮)展示效果

$$e.addevent( container, "mouseleave", this._leave );  

 其中_leave函數是這樣的:

SlideView 圖檔滑動(擴充/收縮)展示效果

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方法。

【滑動對象】

程式初始化時會根據滑動元素建立滑動對象集合。

先擷取滑動元素:

SlideView 圖檔滑動(擴充/收縮)展示效果

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滑動對象集合:

SlideView 圖檔滑動(擴充/收縮)展示效果

this._nodes = $$a.map( nodes, function(node){ return { "node": node }; });  

滑動對象用"node"屬性記錄滑動元素。

然後在_initnodes方法中初始化滑動對象。

每個滑動對象都有3個用來計算滑動目标值的屬性:defaulttarget預設目标值,max展示尺寸,min收縮尺寸。

如果有自定義max尺寸或min尺寸,會根據自定義的尺寸來計算。

程式會優先按max來計算:

SlideView 圖檔滑動(擴充/收縮)展示效果

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來計算:

SlideView 圖檔滑動(擴充/收縮)展示效果

min = math.min( min < 1 ? min * clientsize : min, defaultsize );  

max = clientsize - maxindex * min;  

 同樣,如果min是小數就按百分比計算,再做範圍限制,然後計算得出max。最後得到自定義尺寸計算函數: 

SlideView 圖檔滑動(擴充/收縮)展示效果

getmax = function(){ return max; };  

getmin = function(){ return min; };  

 如果沒有自定義max或min,就根據元素尺寸來計算:

SlideView 圖檔滑動(擴充/收縮)展示效果

getmax = function(o){ return math.max( math.min( o.node[ offset ], clientsize ), defaultsize ); };  

getmin = function(o){ return ( clientsize - o.max ) / maxindex; };  

把元素尺寸作為展示尺寸來計算,同樣要做範圍限制,然後計算收縮尺寸。

得到尺寸計算函數後,再用_each方法曆遍并設定滑動對象:

SlideView 圖檔滑動(擴充/收縮)展示效果

o.current = o.defaulttarget = getdefaulttarget(i);  

o.max = getmax(o); o.min = getmin(o);  

其中current是目前坐标值,在移動計算時作為開始值的。

而defaulttarget是預設目标值,即預設狀态時移動的目标值,根據defaultsize和索引得到。

還要設定當滑鼠進入滑動元素時觸發show展示函數:

SlideView 圖檔滑動(擴充/收縮)展示效果

var node = o.node, show = $$f.bind( this.show, this, i );  

o.show = $$f.bind( function(){  

    this._timerdelay = settimeout( show, this.delay );  

    $$ce.fireevent( this, "enter", i );  

$$e.addevent( node, "mouseenter", o.show );  

要在滑動元素的"mouseenter"事件中觸發,并傳遞目前滑動對象的索引,再加上延時設定就可以了。

【滑動展示】

當滑鼠進入其中一個滑動元素,就會觸發show方法開始展示。

首先執行_setmove方法設定滑動參數,并以索引作為參數。

在_setmove裡面主要是設定計算移動值時需要的目标值、開始值和變化值。

先修正索引,錯誤的索引值會設定為0:

SlideView 圖檔滑動(擴充/收縮)展示效果

this._index = index = index < 0 || index > maxindex ? 0 : index | 0;  

  再根據索引擷取要展示的滑動對象,通過展示對象的min和max得到gettarget目标值函數:

SlideView 圖檔滑動(擴充/收縮)展示效果

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。

然後設定每個滑動對象的參數屬性:

SlideView 圖檔滑動(擴充/收縮)展示效果

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移動函數,用來設定緩動:

SlideView 圖檔滑動(擴充/收縮)展示效果

this._setpos( function(o) {  

    return this.tween( this._time, o.begin, o.change, this.duration );  

});  

利用tween算法,結合目前時間,開始值,改變值和持續時間,就能得到目前要移動的坐标值。

ps:關于tween緩動可以參考tween算法及緩動效果 。

當_time到達duration說明滑動已經完成,再執行一次_targetmove目标值移動函數:

SlideView 圖檔滑動(擴充/收縮)展示效果

this._setpos( function(o) { return o.target; } );  

直接移動到目标值,可以防止可能出現的計算誤差導緻移位不準确。

【關閉和重置】

close方法可以關閉展示,即滑動到預設狀态,預設在移出容器時就會執行。

預設狀态是指全部滑動元素位于defaulttarget預設目标值的狀态。

先用_setmove設定移動參數,當_setmove沒有索引參數時,就會設定目标值為預設目标值:

SlideView 圖檔滑動(擴充/收縮)展示效果

gettarget = function(o){ return o.defaulttarget; }  

完成參數設定後,再執行_easemove進行滑動,跟滑動展示類似。

reset方法可以重置展示,重置的意思是不進行滑動而直接移動到目标值。

如果沒有索引參數,就會直接執行_defaultmove預設值移動函數:

SlideView 圖檔滑動(擴充/收縮)展示效果

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屬性就是用來記錄目前模式要使用的坐标樣式的:

SlideView 圖檔滑動(擴充/收縮)展示效果

this._pos = /^(bottom|top|right|left)$/.test( opt.mode.tolowercase() ) ? regexp.$1 : "left";  

 然後在_setpos方法中使用_pos指定的坐标樣式來設定坐标值:

SlideView 圖檔滑動(擴充/收縮)展示效果

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模式要實作類似下面的效果:

有兩種方法,可以調整元素插入順序:

SlideView 圖檔滑動(擴充/收縮)展示效果
SlideView 圖檔滑動(擴充/收縮)展示效果

<div class="container">  

    <div style="right:0;">2</div>  

    <div style="right:100px;">1</div>  

    <div style="right:200px;">0</div>  

</div>  

 但這樣需要修改dom結構,或者通過zindex設定堆疊順序:

SlideView 圖檔滑動(擴充/收縮)展示效果

    <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>  

顯然設定zindex的方法比較好,程式也用了這個方法。

程式就是用_reverse屬性來判斷是否需要做這些修正。

首先在_initcontainer中,根據_reverse重新設定zindex:

SlideView 圖檔滑動(擴充/收縮)展示效果

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中,擷取預設目标值時也要判斷:

SlideView 圖檔滑動(擴充/收縮)展示效果

getdefaulttarget = this._reverse  

    ? function(i){ return defaultsize * ( maxindex - i ); }  

    : function(i){ return defaultsize * i; },  

當_reverse為true時,由于定點位置是在索引的反方向,設定元素時也應該倒過來設的,是以要用maxindex減一下。

在_setmove中,根據索引設定滑動目标值時,也要判斷:

SlideView 圖檔滑動(擴充/收縮)展示效果

if ( this._reverse ) {  

    var get = gettarget;  

    index = maxindex - index;  

    gettarget = function(o, i){ return get( o, maxindex - i ); }  

}  

不但滑動對象集合的索引要修正,展示對象的索引也要修正。

【自動展示擴充】

這次擴充用的是組合模式,原理參考的imagezoom擴充篇的擴充模式部分 。

不同的是加了一個屬性擴充,用來添加擴充方法:

SlideView 圖檔滑動(擴充/收縮)展示效果

$$.extend( this, prototype );  

注意不能添加到slideview.prototype,這樣會影響到slideview的結構。

“自動展示”要實作的是滑動對象自動輪流展示,并且取消預設狀态而實行強制展示,可以用在圖檔的輪換展示。

隻要在slideview後面加入自動展示擴充程式,并且auto參數設為true就會啟用。

原理也很簡單,就是每次滑動/移動完成後,用定時器執行下一次滑動就行了。

首先在"init"初始化程式中,增加一個_next程式,用來展示下一個滑動對象:

SlideView 圖檔滑動(擴充/收縮)展示效果

this._next = $$f.bind( function(){ this.show( this._index + 1 ); }, this );  

其實就是把目前索引_index加1之後作為show的參數執行。

再增加一個_autonext方法:

SlideView 圖檔滑動(擴充/收縮)展示效果

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:

SlideView 圖檔滑動(擴充/收縮)展示效果

reset.call( this, index == undefined ? this._index : index );  

this._autonext();   

重寫後的reset會強制設定索引來展示,并執行_autonext進行下一次滑動。

【提示資訊擴充】

“提示資訊”效果是指每個滑動對象對應有一個提示資訊(内容)的層(元素)。

這個提示資訊會在滑動對象展示時展示,收縮和關閉時關閉。

隻要加入提示資訊擴充程式,并且tip參數設為true就會啟用。

提示擴充支援四種位置提示:bottom、top、right、left。

在"init"中,根據自定義tipmode擷取_tippos坐标樣式:

SlideView 圖檔滑動(擴充/收縮)展示效果

this._tippos = /^(bottom|top|right|left)$/.test( this.options.tippos.tolowercase() ) ? regexp.$1 : "bottom";  

 接着在"initnodes"定義一個能根據滑動元素擷取提示元素的函數:

SlideView 圖檔滑動(擴充/收縮)展示效果

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來篩選元素,注意可能包含多個樣式,不能直接等于。

得到函數後,再建立提示對象:

SlideView 圖檔滑動(擴充/收縮)展示效果

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"中設定提示移動目标值:

SlideView 圖檔滑動(擴充/收縮)展示效果

var maxindex = this._nodes.length - 1;  

    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方法:

SlideView 圖檔滑動(擴充/收縮)展示效果

var pos = this._tippos;  

    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作為參數:

SlideView 圖檔滑動(擴充/收縮)展示效果

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//關閉時目标坐标