Home » jQuery 應用

[jQ]用 jQuery 做畫廊 – jQuery 版的 Nike 首頁產品展示

範例 1
範例 2
範例 3
沒錯!只要 2,400 元就能獲得我們團隊完整的協助,讓效果能迅速的整合到您的網站,並保證瀏覽器的相容性。
立刻申請!

昨天梅干傳了一個 Nike.com.tw 的網址過來,讓筆者以為梅干要轉行賣鞋或是透過他買鞋可以拿到流血價咧!結果是...看到了它首頁的產品展示效果蠻不錯的,想討論看看是否能用 jQuery 來做出類似的功能。



稍微玩一下 Nike 的效果時會發現,產品項目的排列是左右都是小圖,只有中間顯示的是大圖。而當點擊右邊的產品時,全部的項目會往左移動,若是點擊左邊的產品時,則是往右移動。中間較大的區塊是顯示所點擊到的項目。另外,左右兩邊的項目預設是呈現半透明的效果,當滑鼠移上去時才會變成不透明。且當左右兩邊項目移動時,此時也是變成不透明的。

總結一下要實現的功能:
1.產品項目的排列要變程左右小圖,中間大圖的樣式。
2.點擊左邊項目就整個往右移;點擊右邊項目就整個往左移。中間區塊就移到所點擊的項目。
3.左右項目預設是半透明,當滑鼠移到某項目時才變成不透明,且當點擊後移動時也是不透明。


為了程式方便撰寫,筆者就把它設計成使用 3 組 ul 來當產品項目清單:



圖中所看到的都是獨立的一組 ul 元素,雖然每一組的第一個項目都是不一樣的,但這樣當大家都往前左或是往右移動時是能一致的。只要把它們組起來的話就會變成:



接著就動手來設計 HTMLCSS 囉:

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_rightnike_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 清單後再一一綁定其事件:

檢視原始碼 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
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 的處理:

檢視原始碼 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
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;
	}
});

嘿~~快來看看效果變成怎樣:



是不是變的更有質感的呢!各位只要把圖片及遮罩替換後,就能有屬於自己的產品展示功能囉。

範例 1 範例 2 範例 3
2010/09/08 修正當圖片超過 5 張後的移動問題。
2011/10/11 若使用 jQuery 1.6 (含)以後版本的話,請記得把程式中的 .attr('className') 改成 .attr('class')。

檔案描述
基本的範例檔案(免空) 開始下載
基本的範例檔案 會員限定

92 筆針對 [jQ]用 jQuery 做畫廊 – jQuery 版的 Nike 首頁產品展示 的迴響

  1. 是否可加入影片播放?如:Youtube影片
    說明:
    左右是顯示Youtube影片縮圖,當點擊某張縮圖移到中間時就開始播放影片
    當點右邊一張縮圖時,目前影片停止播放並往左移動變成縮圖,然後開始播放剛點擊的影片

  2. 請問男丁老師!是不是無法運用到WP!
    因為我放上去會衝突!
    不知道是不是我的WP設置問題!
    我有把其他的js檔先關掉可是一樣不行!

  3. 請問男丁老師,「自動播放要使用 setTimeout() 來完成」「宣告timer, speed = 2000;// 計時器及輪播切換的速度」「timer = setTimeout(autoClick, speed);」「要有 autoClick 這個 function 」....可以完整的告知這一段要怎麼寫嗎?要把這段加在何處呢?不會寫function的菜鳥敬上!!

發表迴響