昨天梅干傳了一個 Nike.com.tw 的網址過來,讓筆者以為梅干要轉行賣鞋或是透過他買鞋可以拿到流血價咧!結果是...看到了它首頁的產品展示效果蠻不錯的,想討論看看是否能用 jQuery 來做出類似的功能。
稍微玩一下 Nike 的效果時會發現,產品項目的排列是左右都是小圖,只有中間顯示的是大圖。而當點擊右邊的產品時,全部的項目會往左移動,若是點擊左邊的產品時,則是往右移動。中間較大的區塊是顯示所點擊到的項目。另外,左右兩邊的項目預設是呈現半透明的效果,當滑鼠移上去時才會變成不透明。且當左右兩邊項目移動時,此時也是變成不透明的。
總結一下要實現的功能:
1.產品項目的排列要變程左右小圖,中間大圖的樣式。
2.點擊左邊項目就整個往右移;點擊右邊項目就整個往左移。中間區塊就移到所點擊的項目。
3.左右項目預設是半透明,當滑鼠移到某項目時才變成不透明,且當點擊後移動時也是不透明。
為了程式方便撰寫,筆者就把它設計成使用 3 組 ul 來當產品項目清單:
圖中所看到的都是獨立的一組 ul 元素,雖然每一組的第一個項目都是不一樣的,但這樣當大家都往前左或是往右移動時是能一致的。只要把它們組起來的話就會變成:
接著就動手來設計 HTML 及 CSS 囉:
1 2 3 4 5 6 7 8 9 10 11 | <body> <div class="nike"> <ul> <li><a href="#"><img src="small01.gif" /></a></li> <li><a href="#"><img src="small02.gif" /></a></li> <li><a href="#"><img src="small03.gif" /></a></li> <li><a href="#"><img src="small04.gif" /></a></li> <li><a href="#"><img src="small05.gif" /></a></li> </ul> </div> </body> |
一開始只是原始的 ul 產品項目,筆者等等會透過 jQuery 來產生需要的 3 組 ul 並放在 nike_left, nike_right 及 nike_main 區塊中。
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 | ul, li { margin: 0; padding: 0; list-style: none; } a img { border: none; } .nike { width: 300px; height: 100px; position: relative; } .nike div ul { width: 9999px; position: absolute; } .nike div ul li { float: left; } .nike div ul li a { display: block; width: 50px; /* 小圖的寬 */ height: 50px; /* 小圖的高 */ } .nike .nike_left { position: absolute; left: 0; top: 25px; width: 100px; /* 小圖的寬 * 2 */ height: 50px; overflow: hidden; border: solid 1px #fff; } .nike .nike_right { position: absolute; right: 0; top: 25px; width: 100px; /* 小圖的寬 * 2 */ height: 50px; overflow: hidden; border: solid 1px #fff; } .nike .nike_main { position: absolute; left: 100px; /* 小圖的寬 * 2 */ top: 0; width: 100px; /* 大圖的寬 * 1 */ height: 100px; overflow: hidden; } .nike .nike_main ul li a { width: 100px; /* 大圖的寬 */ height: 100px; /* 大圖的寬 */ } |
再來就要打起精神仔細看了喔,筆者要先用 jQuery 來產生 ul 清單後再一一綁定其事件:
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 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | $(function(){ // 先取得 .nike 及原始的 ul 項目 // 接著產生三組 div 並各自包一個 ul 項目 // 再來取得一些額外的參數、小圖及大圖的名稱 var $nike = $('.nike'), $source = $nike.children('ul').remove(), $leftUl = $('<div class="nike_left"><ul></ul></div>').children(), $rightUl = $('<div class="nike_right"><ul></ul></div>').children(), $mainUl = $('<div class="nike_main"><ul></ul></div>').children(), $sourceLi = $source.children(), _liStr = $source.html(), _itemLen = $sourceLi.length, _middle = Math.ceil(_itemLen / 2), _small = /small/ig, _big = 'big', _smallWidth = 50, _bigWidth = 100; // 幫左邊 ul 清單加入 li 項目 $leftUl.append(getLiItem(_middle - 2 - 1, _itemLen) + _liStr); // 幫右邊 ul 清單加入 li 項目 $rightUl.append(getLiItem(_middle, _itemLen) + _liStr + getLiItem(0, _itemLen - _middle)); // 幫中間 ul 清單加入 li 項目 $mainUl.append((getLiItem(_middle - 1, _itemLen) + _liStr).replace(_small, _big)); // 把 ul 清單部份都加到 .nike 中 $nike.append($leftUl.parent(), $rightUl.parent(), $mainUl.parent()); // 幫右邊 ul li a 加上 click 事件並產生透明度 // 當點擊到時往左移動項目 $rightUl.find('li a').click(function(){ move(($(this).parent().index() + 1) % $rightUl.children().length); return false; }).fadeTo(200, 0.5); // 幫左邊 ul li a 加上 click 事件並產生 0.5 的透明度 // 當點擊到時往右移動項目 $leftUl.find('li a').click(function(){ var _index = $(this).parent().index(); if(_index < 2){ $leftUl.add($rightUl).add($('.nike_right.fake ul, .nike_left.fake ul')).css('left', _itemLen * _smallWidth * -1); $mainUl.add($('.nike_main.fake ul')).css('left', _itemLen * _bigWidth * -1); _index += _itemLen; } move((_index - 2) % $leftUl.children().length); return false; }).fadeTo(200, 0.5); // 幫左右兩邊的 ul li a 加上 hover 事件 // 當滑鼠移到項目時就變成不透明;移出則再變成 0.5 的透明度 $rightUl.add($leftUl).find('li a').hover(function(){ $(this).fadeTo(200, 1); }, function(){ $(this).fadeTo(200, 0.5); }); // 控制移動的函式 function move(i){ // 移動左右清單 // 移動時變成不透明 $leftUl.add($rightUl).stop(false, true).animate({ left: i * _smallWidth * -1 }, changeLeft).find('li a').css('opacity', 1); // 移動中間清單 $mainUl.stop(false, true).animate({ left: i * _bigWidth * -1 }, changeLeft); } // 當完成移動後的處理函式 function changeLeft(){ var $this = $(this), dis = $this.parent().attr('className') == 'nike_main' ? _bigWidth : _smallWidth, i = (parseInt($this.css('left'), 10) || 0) / dis * -1; // 處理左右清單的位移 if(i >= _itemLen){ $(this).css('left', dis * (i - 5) * -1); } // 把左右清單的 li a 變成 0.5 的透明度 if(dis==_smallWidth){ $(this).find('li a').css('opacity', 0.5); } } // 組成 li 項目的函式 function getLiItem(startIndex, endIndex){ var rtvl = ''; for(var i=startIndex;i<endIndex;i++){ rtvl += '<li>' + $sourceLi.eq(i).html() + '</li>'; } return rtvl; } }); |
程式碼雖然看起來很長,但基本上就是先產生 3 組區塊及清單,然後加上 click 及移動的事件而已。當完成後就能看到很類似 Nike 的陽春畫面了:
各位可以試著玩看看,看是否有達到一開始筆者所預訂的那幾項功能需求!接著更大的難題來了,要如何幫它加上美美的外框呢?
筆者這邊把外框當成是遮罩的一種,因此只要讓遮罩能在最上層並中空的話,這樣就有加上外框的效果了:
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* .mask 為遮罩用的 div */ .nike .mask { position: absolute; left: 0; top: 0; width: 300px; height: 100px; background: transparent url(mask.png); /* 遮罩圖片 */ z-index: 2; } .nike .fake { z-index: 3; } |
利用設定 z-index 的方式來達到階層的控制,但 IE 6 不支援透明的 PNG24 圖檔,所以...升級吧!現在已經有了 .mask 樣式了,接下來一樣是利用程式來加上它並做一些 Magic 的處理:
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 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | $(function(){ // 先取得 .nike 及原始的 ul 項目 // 接著產生三組 div 並各自包一個 ul 項目 // 再來取得一些額外的參數、小圖及大圖的名稱 var $nike = $('.nike'), $source = $nike.children('ul').remove(), $leftUl = $('<div class="nike_left"><ul></ul></div>').children(), $rightUl = $('<div class="nike_right"><ul></ul></div>').children(), $mainUl = $('<div class="nike_main"><ul></ul></div>').children(), $sourceLi = $source.children(), _liStr = $source.html(), _itemLen = $sourceLi.length, _middle = Math.ceil(_itemLen / 2), _small = /small/ig, _big = 'big', _smallWidth = 50, _bigWidth = 100; // 幫左邊 ul 清單加入 li 項目 $leftUl.append(getLiItem(_middle - 2 - 1, _itemLen) + _liStr); // 幫右邊 ul 清單加入 li 項目 $rightUl.append(getLiItem(_middle, _itemLen) + _liStr + getLiItem(0, _itemLen - _middle)); // 幫中間 ul 清單加入 li 項目 $mainUl.append((getLiItem(_middle - 1, _itemLen) + _liStr).replace(_small, _big)); // 把 ul 清單部份都加到 .nike 中 $nike.append($leftUl.parent(), $rightUl.parent(), $mainUl.parent()); // 加入遮罩 .mask $nike.append('<div class="mask"></div>'); // 加入控制用的遮罩 ul $nike.append($leftUl.parent().clone().addClass('fake'), $rightUl.parent().clone().addClass('fake'), $mainUl.parent().clone().addClass('fake')); // 隱藏控制用的遮罩 ul 中的圖片 $nike.find('.fake img').css('opacity', 0); // 幫左右兩邊的 ul li a 加上 0.5 的透明度 $rightUl.add($leftUl).find('li a').fadeTo(200, 0.5); // 幫控制用的右邊遮罩 ul li a 加上 click 事件 // 當點擊到時往左移動項目 $('.nike_right.fake').find('li a').click(function(){ move(($(this).parent().index() + 1) % $rightUl.children().length); return false; }); // 幫控制用的左邊遮罩 ul li a 加上 click 事件 // 當點擊到時往右移動項目 $('.nike_left.fake').find('li a').click(function(){ var _index = $(this).parent().index(); if(_index < 2){ $leftUl.add($rightUl).add($('.nike_right.fake ul, .nike_left.fake ul')).css('left', _itemLen * _smallWidth * -1); $mainUl.add($('.nike_main.fake ul')).css('left', _itemLen * _bigWidth * -1); _index += _itemLen; } move((_index - 2) % $leftUl.children().length); return false; }); // 幫控制用的左右兩邊遮罩的 ul li a 加上 hover 事件 // 當滑鼠移到項目時就變成不透明;移出則再變成 0.5 的透明度 $('.nike_right.fake, .nike_left.fake').find('li a').hover(function(){ var $this = $(this); ($this.parents('div').attr('className').indexOf('nike_right')>-1 ? $rightUl : $leftUl).children('li').eq($this.parent().index()).children().fadeTo(200, 1); }, function(){ var $this = $(this); ($this.parents('div').attr('className').indexOf('nike_right')>-1 ? $rightUl : $leftUl).children('li').eq($this.parent().index()).children().fadeTo(200, 0.5); }); // 控制移動的函式 function move(i){ // 移動左右清單 // 移動時變成不透明 $leftUl.add($rightUl).add($('.nike_right.fake ul, .nike_left.fake ul')).stop(false, true).animate({ left: i * _smallWidth * -1 }, changeLeft).find('li a').css('opacity', 1);; // 移動中間清單 $mainUl.add($('.nike_main.fake ul')).stop(false, true).animate({ left: i * _bigWidth * -1 }, changeLeft); } // 當完成移動後的處理函式 function changeLeft(){ var $this = $(this), dis = $this.parent().attr('className').indexOf('nike_main')>-1 ? _bigWidth : _smallWidth, i = (parseInt($this.css('left'), 10) || 0) / dis * -1; // 處理左右清單的位移 if(i >= _itemLen){ $(this).css('left', dis * (i - _itemLen) * -1); } // 把左右清單的 li a 變成 0.5 的透明度 if(dis==_smallWidth){ $(this).find('li a').css('opacity', 0.5); } } // 組成 li 項目的函式 function getLiItem(startIndex, endIndex){ var rtvl = ''; for(var i=startIndex;i<endIndex;i++){ rtvl += '<li>' + $sourceLi.eq(i).html() + '</li>'; } return rtvl; } }); |
嘿~~快來看看效果變成怎樣:
是不是變的更有質感的呢!各位只要把圖片及遮罩替換後,就能有屬於自己的產品展示功能囉。
老師您好,
我試著在範例中加入左右移動鍵及自動播放功能,
但只要圖片播放一輪,
圖片就會亂跑,
我有將檔案寄至老師的gmail信箱,
可以請您幫我看看嗎?
感謝您~
老師您好:
我是初學者,想要把老師的這個範例放到用Wordpress架的網站上,
我將老師的範例下載後,貼到Wordpress的文章內容,但不管怎麼試,
都沒有辦法呈現老師範例的效果,請問老師,如果想要將老師的範例用在Wordpress的網站上,
需要修改哪些地方嗎?
感謝老師無私的分享。
也許是 CSS 有所衝突所造成的, 不過還是要看到套上後你的網站畫面才知道問題在那!
南丁老師您好:
感謝您百忙之中作回覆,下面網址是我借朋友的測試網站使用:
http://peikowine.comyr.com/pw_robin/jquery-測試/
範例程式碼內容都沒有變,只有更換圖檔路徑,而且圖檔也沒有依據CSS設定變更大小?
能否請教老師問題出在哪裡?
感謝老師
你這看起來是直接把它當成文章在發表了耶XD
應該是要把程式放在主題中才對
南丁老師您好:
感謝您的指導,我再試看看。
老師您好,想請問一下如果要用滑鼠拖曳換圖的效果,要如何修改呢?謝謝