一般 Flash 廣告或是商品的輪播大多是不間斷的,所以就常會有網友問說 jQuery 的範例是否能做到不間斷的輪播呢?答案其實連想都不用想的也知道是可以的,且要達到同樣效果的方法有好幾種,筆者此次就針對一種較簡單但效能會差一點點的方式來介紹。
首先當然是要準備好 HTML(圖片還是一樣從梅干那邊 A 來的):
檢視原始碼 HTML
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <body> <div id="abgne-block-20110406"> <div class="slides"> <ul> <li><a href="#"><img src="images/1.jpg" alt="" /></a></li> <li><a href="#"><img src="images/2.jpg" alt="" /></a></li> <li><a href="#"><img src="images/3.jpg" alt="" /></a></li> <li><a href="#"><img src="images/4.jpg" alt="" /></a></li> <li><a href="#"><img src="images/5.jpg" alt="" /></a></li> </ul> </div> <a href="#" class="prev"><</a> <a href="#" class="next">></a> </div> </body> |
這次的範例會多加一個外框,因此就會看到有多出一層來包裹 ul。接著就來看 CSS 怎樣排版:
檢視原始碼 CSS
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | ul, li { margin: 0; padding: 0; list-style: none; } a img { border: none; } #abgne-block-20110406 { margin: 0 auto; width: 632px; /* 框架圖片的寬 */ height: 438px; /* 框架圖片的高 */ position: relative; background: url('images/frame.gif') no-repeat; } #abgne-block-20110406 a.prev, #abgne-block-20110406 a.next { position: absolute; top: 173px; display: block; width: 56px; /* 左右鈕圖片的寬 */ height: 53px; /* 左右鈕圖片的高 */ text-indent: -9999px; } #abgne-block-20110406 .prev { background: url('images/left.png') no-repeat; } #abgne-block-20110406 .next { background: url('images/right.png') no-repeat; right: 0; } #abgne-block-20110406 .slides { overflow: hidden; position: relative; top: 32px; left: 30px; width: 574px; /* 框架中間區塊的寬 */ height: 376px; /* 框架中間區塊的高 */ } #abgne-block-20110406 .slides ul { position: absolute; width: 9990px; height: 100%; } #abgne-block-20110406 .slides li { width: 574px; /* 框架中間區塊的寬 */ height: 100%; float: left; } |
在動手寫程式前先來看看畫面吧~
是不是經過巧手裝飾過後就變的很有質感了呢!接著透過 jQuery 的魔法來完成最後的步驟:
檢視原始碼 JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | $(function(){ // 先取得必要的元素並用 jQuery 包裝 // 再來取得 $block 的寬度及設定動畫時間 var $block = $('#abgne-block-20110406'), $slides = $block.find('.slides'), $ul = $slides.find('ul'), _width = $slides.width(), _left = _width * -1, _animateSpeed = 400; // 先把最後一個 li 的內容插入到第一個 li 前面 // 並設定 $ul 的 left 及 width $ul.find('li:first').before($ul.find('li:last')).end().css({ left: _left, width: _width * ($ul.find('li').length + 1) }); // 當點擊到 a.prev 時 $block.find('a.prev').click(function(){ // 移動 $ul $ul.stop(false, true).animate({'left' : _left + _width}, _animateSpeed, function () { // 把最後一個 li 的內容插入到第一個 li 前面 $ul.find('li:first').before($ul.find('li:last')).end().css('left', _left); }); return false; }); // 當點擊到 a.next 時 $block.find('a.next').click(function(){ // 移動 $ul $ul.stop(false, true).animate({'left' : _left - _width}, _animateSpeed, function () { // 把第一個 li 的內容插入到最後一個 li 後面 $ul.find('li:last').after($ul.find('li:first')).end().css('left', _left); }); return false; }); $block.find('a').focus(function(){ this.blur(); }); }); |
其中比較關鍵的是 .after() 及 .before() 的地方:
檢視原始碼 JavaScript
1 | $ul.find('li:last').after($ul.find('li:first')).end().css('left', _left); |
它會馬上的把第一個 li 的內容再插入到最後一個 li 的後面,也就產生了不間斷的效果。不過一直插入移除 DOM 是會耗一點效能啦!
最後要讓它能自動切換的話,則得再加上計時器功能:
檢視原始碼 JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | $(function(){ // 先取得必要的元素並用 jQuery 包裝 // 再來取得 $block 的寬度及設定動畫時間 var $block = $('#abgne-block-20110406'), $slides = $block.find('.slides'), $ul = $slides.find('ul'), _width = $slides.width(), _left = _width * -1, _animateSpeed = 400, // 加入計時器, 輪播時間及控制開關 timer, _showSpeed = 3000, _stop = false; // 先把最後一個 li 的內容插入到第一個 li 前面 // 並設定 $ul 的 left 及 width $ul.find('li:first').before($ul.find('li:last')).end().css({ left: _left, width: _width * ($ul.find('li').length + 1) }); // 當點擊到 a.prev 時 var $prev = $block.find('a.prev').click(function(){ // 移動 $ul $ul.stop(false, true).animate({'left' : _left + _width}, _animateSpeed, function () { // 把最後一個 li 的內容插入到第一個 li 前面 $ul.find('li:first').before($ul.find('li:last')).end().css('left', _left); // 當移動到正確位置後, 依判斷來啟動計時器 if(!_stop) { clearTimeout(timer); timer = setTimeout(move, _showSpeed); } }); return false; }); // 當點擊到 a.next 時 var $next = $block.find('a.next').click(function(){ // 移動 $ul $ul.stop(false, true).animate({'left' : _left - _width}, _animateSpeed, function () { // 把第一個 li 的內容插入到最後一個 li 後面 $ul.find('li:last').after($ul.find('li:first')).end().css('left', _left); // 當移動到正確位置後, 依判斷來啟動計時器 if(!_stop) { clearTimeout(timer); timer = setTimeout(move, _showSpeed); } }); return false; }); // 如果滑鼠移入 $block 時 $block.hover(function(){ // 關閉開關及計時器 _stop = true; clearTimeout(timer); }, function(){ // 如果滑鼠移出 $block 時 // 開啟開關及計時器 _stop = false; timer = setTimeout(move, _showSpeed); }).find('a').focus(function(){ this.blur(); }); // 計時器使用 function move(){ $next.click(); }; timer = setTimeout(move, _showSpeed); }); |
男丁格爾老師您好:
點了左右後範例會連續跳兩張,需要調整哪個參數,才可以讓他不會跳著播放呢??謝謝老師的解答 ^^
這要看你的範例才知道那邊有問題, 如果可以的話把檔案整包寄給我看看
這問題是否有解決呢?如果有可否公佈,謝謝~
JOHNNY 並沒有寄檔案給我測試,所以我不知道這問題在那。
應該是時間差產生的問題, 範例已更新了。
請問老師,如何把move切換圖,變成fade漸出漸入效果呢?
這範例就是滑動, 這跟 html 及 css 會有對應關係的。
要淡入淡出可以參考: 淡入淡出式的切換影像
請問老師:
如果還要加上 [jQ]用 jQuery 做廣告 – 左右水平廣告輪播 這篇裡面的圓點選單要怎麼寫呢?
就參考其中產生 control 的部份
這個範例一次只出現一張圖
那如果一次要出現6張圖 然後每次移動只移一張的話 那要怎麼改呢
原理基本上是一樣的, 只是我現在顯示的寬度是配合圖片的寬度
你可以試著修改移動時的寬度就可以了
感謝~!~~
(關於lazyload)
男丁老師,不好意思 請教您一個問題喔, 我正在設計的網站 有非常大量的圖片(粗略估計200-300張,約350MB), 網站呈現圖片的方式就像這篇教的畫廊一樣, 每個畫廊都是由click某個class 然後顯現出來的。
圖片非常大量, 每次載入都需要滿多時間, 所以試著用lazyload的方式(event:"click")延遲載入圖片, 網頁開啟的時間明顯變快了, 但問題是 每次開啟一個div畫廊, 就要click一下才跑出一張圖片, 然後按">"下一張, 下一張還是要在click一下才顯現出來。
我希望的方式是, 每次開啟一個div畫廊, 就觸發整個div的圖片下載, 有兩個地方需要解決, 第一就是觸發載入圖片的方式要改成$(".something").click(function(){的方式; 第二就是一次要載入整個div的圖片, 不是只有一張。
這個問題對我來說真的很棘手, 剛開始學網頁設計一個多月, 因為實習的關係自己才有這個學習的機會, 但爬文總找不到解決的方法, 懇請男丁老師解答, 謝謝!
你可以找像是 preload 的外掛套件, 當你點了某個畫廊時, 就把該畫廊中的 img 都用 preload 的方式來預載!
先試看看~因為沒有你的範例, 所以無法給你很明確的 code..
男丁老師, 我試著嘗試你說的preload, 我的js是這樣
;(function($){$.preload=function(){var tmp=[],i=arguments.length;for(;i-;)tmp.push($(").attr('src',arguments[i]));};})(jQuery);
/——————————-/
但是我還沒用$.preload('/img/space.gif'); 來呼叫圖片, 當打開網頁時就全部下載了, 不是應該等我用$.preload之後, 才會下載圖片嗎?
懇請老師解答,謝謝
唔, 因為你把圖片的語法都寫在 html 上, 所以頁面載入時就自動下載了
我沒有那麼多圖片可以測試, 不過也許你的圖片語法不要直接寫在網頁中, 可以利用 preload 後再加入
老師,我的問題童之前樓上問過的:這個範例一次只出現一張圖
那如果一次要出現6張圖 然後每次移動只移一張的話 那要怎麼改呢
但是我修改後圖片跳轉的寬度沒有問題了,但畫面顯示的圖片數始終只有一張,沒辦法排列出其他圖片
還請幫幫我,謝謝
要幫也要你把你的程式寄給我看看啊XD
你好啊男丁老師, 我發現了有一個bug, 當相片少於3張便會出現問題, 如果只有兩張的話, 會因為只能走出兩張圖而斷了, 另外如果只有一張的, 會什麼都走不出來。因為我有後台, 所以在煩惱如個修改。
唔, 因為這範例是用搬移的方式來做出不間斷的效果, 若要能不限圖片數也有效果的話, 則要改改方式才行哩~
老師您好,
我一直有個疑問,
為什麼後面得加上 return false ?
大大 你好:
想請教一下這個特效有支援觸控的嗎?就是手機和平板上可使用
自己有在寫網頁有小小研究 感恩~
暫時還不支援, 接下來 2-3 月時會重新用最新版的 jQuery 來改寫範例, 到時候進階範例的部份都會加上 touch 的功能