2010年3月14日 星期日

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

 轉貼自:http://abgne.tw/jquery/apply-jquery/jquery-nike-gallery.html

昨天梅干傳了一個 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 清單後再一一綁定其事件:


?檢視原始碼 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
$(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(_liStr + getLiItem($sourceLi, 0, _middle));
// 幫右邊 ul 清單加入 li 項目
$rightUl.append(getLiItem($sourceLi, _middle, _itemLen) + _liStr + getLiItem($sourceLi, 0, _itemLen - _middle));
// 幫中間 ul 清單加入 li 項目
$mainUl.append((getLiItem($sourceLi, _middle - 1, _itemLen) + _liStr).replace(_small, _big));
// 把 ul 清單部份都加到 .nike 中
$nike.append($leftUl.parent(), $rightUl.parent(), $mainUl.parent());

// 幫右邊 ul li a 加上 click 事件並產生 0.5 的透明度
// 當點擊到時往左移動項目
$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<=1){
$leftUl.add($rightUl).css('left', _itemLen * _smallWidth * -1);
$mainUl.css('left', _itemLen * _bigWidth * -1);
_index += _itemLen;
}
_index = (_index - (_itemLen - _middle)) % $leftUl.children().length;
move(_index);

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(source, startIndex, endIndex){
var rtvl = '';
for(var i=startIndex;i<endIndex;i++){
rtvl += '<li>' + source.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(_liStr + getLiItem(0, _middle));
// 幫右邊 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<=1){
$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 - (_itemLen - _middle)) % $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;
}
});


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







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



範例瀏覽:

http://demonstration.abgne.tw/jquery/0019/0019_1.html

http://demonstration.abgne.tw/jquery/0019/0019_2.html

http://demonstration.abgne.tw/jquery/0019/0019_3.html
"

沒有留言:

張貼留言

Related Posts with Thumbnails