類似於幻燈片的切換效果,有時需要在網頁中完成一些圖片的自動切換效果,比如廣告,宣傳,產品介紹之類的,那麼單純的切就沒意思了,需要在切換的時候通過一些效果使得切換生動些。 比較常用之一的就是窗帘切換了。 先貼上完成的效果。 實現原理不複雜,在動的一條一條的稱之為“窗帘條”或者是“strip”,每一個s
類似於幻燈片的切換效果,有時需要在網頁中完成一些圖片的自動切換效果,比如廣告,宣傳,產品介紹之類的,那麼單純的切就沒意思了,需要在切換的時候通過一些效果使得切換生動些。
比較常用之一的就是窗帘切換了。
先貼上完成的效果。
實現原理不複雜,在動的一條一條的稱之為“窗帘條”或者是“strip”,每一個strip都是一個div,類似於雪碧圖的方式將其背景圖的位置設置為strip的可視位置,然後用jquery的animate讓他們按照一定規律動起來就完成窗帘切換效果了。
為了使用方便,將這個功能作為jquery的插件方式進行編寫。
插件名:bobenut.curtain.jquery.js
(function (jquery) { jquery.fn.curtain = function (options) { //TODO } })(jQuery);
調用頁面
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <style> #curtain { width: 800px; height: 600px; position: relative; overflow: hidden; margin:0 auto; } </style> </head> <body> <div id="curtain" > <img src="1.jpg"/> <img src="2.jpg"/> <img src="3.jpg"/> <img src="4.jpg"/> </div> <script type='text/javascript' src="jquery-1.11.3.min.js"></script> <script type='text/javascript' src="../src/bobenut.curtain.jquery.js"></script> <script type='text/javascript'> $('#curtain').curtain(); </script> </body> </html>
通過JQuery選擇了包含圖片的div後直接調用即可。
$('#curtain').curtain();
框架寫完了,接下去進入初始化環節。
初始化包括:初始化尺寸、動畫容器、被切換的圖片,各個窗帘條的生成,預設背景,切換時用到的時間參數。
這些個初始化操作寫在一個函數里顯然會比較龐大,而且未來需要增加的功能都要動這麼一個函數,顯然不明智,那麼就把他們按照初始化的職能進行拆分。
那麼這麼多初始化函數的調用就成了問題,難道要硬寫每個函數進行獨立調用?顯然這種方式是很low的。
像這樣每個函數都是具備相同的輸入參數,都沒有返回結果,那麼可以說是相同形態的,可以採用迭代器設計模式進行調用。
所謂的迭代器就是順序訪問各元素,並且不用關心各元素的細節,其實就是迴圈訪問,對於這些個初始化函數的調用我們就可以採用迭代器模式進行調用,下麵各函數定義完後進行迭代器模式的調用。
初始化的結果肯定要找地方放,作為基本的環境上下文context供給後面的切換使用。
在本插件模塊中定義個模塊級的變數context。
所有初始化的結果都保存在context中。
var context = {};
接下來是各個初始化操作函數
1)初始化容器
function initContainer(options) { context.$container = options.$container; }
容器就是包含一組圖片的div,options是調用時傳遞進來的參數,因為這裡的container是用jquery選擇來的,所以加個$以示區分。
2)初始化尺寸
function initSize(options) { context.stripCount = options.stripCount; context.containerWidth = options.width.replace('px', ''); context.containerHeight = options.height.replace('px', ''); context.stripWidth = context.containerWidth / context.stripCount; context.stripHeight = context.containerHeight; }
獲取容器的大小,計算strip的大小。
3)初始化容器內的所有圖片
function initImgs(options) { context.imgSrcs = []; context.$container.children().each(function (index, element) { var $element = $(element); $element.css('display', 'none'); context.imgSrcs.push($element.attr('src')); }); context._imgCurrentIndex = 0; context.nextImgSrc = function () { if (++context._imgCurrentIndex > context.imgSrcs.length - 1) { context._imgCurrentIndex = 0; } return context.imgSrcs[context._imgCurrentIndex]; }; }
一上來了把需要切換的圖片全部隱藏,並把他們的url保存在數組中以便於切換時使用。
提供一個獲取下一張圖片url的方法,使得在切換時能方便獲取下一張圖片的url。
4)初始化strip
function initStrips(options) { context.$strips = []; for (var i = 0; i < context.stripCount; i++) { var $strip = jquery('<div></div>'); $strip.css('background-size', context.containerWidth + 'px ' + context.containerHeight + 'px'); $strip.css('background-position-x', i * context.stripWidth * -1 + 'px'); $strip.css('background-position-y', '0px'); $strip.css('background-repeat', 'no-repeat'); $strip.css('position', 'absolute'); $strip.css('left', (i * context.stripWidth) + 'px'); $strip.css('top', context.stripHeight + 'px'); $strip.css('width', context.stripWidth + 'px'); $strip.css('height', context.stripHeight + 'px'); $strip.css('display', 'block'); $strip.css('overflow', 'hidden'); $strip.css('zoom', '1'); context.$strips.push($strip); context.$container.append($strip); } }
生成所有的strip,給她們設置預設的大小,將要切換的圖設成背景圖,通過background-position-x和y調整背景圖的顯示位置,然後將strip保存於數組中便於使用。
5)初始化預設背景
function initDefaultBackground() { context.$container.css('background-image', 'url(' + context.imgSrcs[0] + ')'); context.$container.css('background-size', context.containerWidth + 'px ' + context.containerHeight + 'px'); }
預設將第一張圖片作為容器的背景。
6)初始化切換時間參數
function initTime(options) { context.interval = options.interval; context.baseDelay = options.baseDelay; context.delayIncrement = options.delayIncrement; }
設置前後圖片的切換標準間隔時間interval,切換時每個strip的切換延遲時間和延遲增量時間。
各個初始化函數完成,接下來採用迭代器模式對各個初始化函數進行調用。
function init(options) { var initFuncs = [initContainer, initSize, initImgs, initStrips, initDefaultBackground, initTime]; for (var i = 0, f; f = initFuncs[i++];) { f(options); } }
在這裡,按照各初始化函數的優先順序,把他們放到一個數組中,通過迴圈這個數組,對每一個函數進行調用,好處就是,新加一個初始化函數的時候,只需往數組的末尾添加即可,甚至可以把初始化函數數組定義到外部,這樣,init函數就符合開閉原則了。
jquery有一種更高大上的迭代處理方法就是each,那麼就對init函數略加修改。
function init(options) { var initFuncs = [initContainer, initSize, initImgs, initStrips, initDefaultBackground, initTime]; jquery.each(initFuncs,function(i,f){ f(options); }); }
each函數的第一個參數是被迭代的對象或數組,第二個參數是迭代每一個元素時的處理回調函數,好處就是,迴圈的事您就別管了,只關心處理。
至此,初始化函數的定義完成。
為了完成init函數的調用,需要考慮生成預設的options,因為外部可以不傳遞任何參數。
然後完成對init函數的調用。
function setDefaultOptions(options, $container) { options = options || {}; options.$container = $container; options.width = options.width || '800px'; options.height = options.height || '600px'; options.stripCount = options.stripCount || 10; options.interval = options.interval || 2; options.baseDelay = options.baseDelay || 400; options.delayIncrement = options.delayIncrement || 80; return options; } jquery.fn.curtain = function (options) { init(setDefaultOptions(options, this));
}
通過setDefaultOptions函數負責確保各個必須的參數都有預設值。
然後將規整過的options作為init的輸入,對init函數進行調用。
至此,通過迭代器的設計模式完成了各個初始化函數的定義和調用。
下一篇繼續:《javascript設計模式實踐之模板方法--具有百葉窗切換圖片效果的JQuery插件(二)》
代碼:戳