在開始介紹之前,請各位先到 HTC 網站看一下他們首頁長怎樣。

有沒有覺得 HTC 網站上方的 Flash 選單很有趣呢!這次筆者就是要教各位怎樣用 jQuery 做出一個山寨版的 HTC 首頁選單。
我們一樣先看 HTML 選單的部份:
1 2 3 4 5 6 7 8 9 10 11 | <body> <ul id="menu"> <li><a href="#" id="home">Home</a></li> <li><a href="#" id="abgne_tw">男丁</a></li> <li><a href="#" id="jellyyoyo">小神童</a></li> <li><a href="#" id="jquery">jQuery</a></li> <li><a href="#" id="flycan">飛肯</a></li> </ul> <div class="bhr"></div> <span id="menuMask"></span> </body> |
每一個連結都有各自的 id,這樣比較方便等下的 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 | body { margin: 0; padding: 0; } #menu { float: right; margin: 50px 0 0; list-style: none; } #menu li { float: left; } #menu li a { display: block; width: 113px; height: 38px; text-indent: -9999px; } #home { background-image: url('home.png'); } #abgne_tw { background-image: url('abgne_tw.png'); } #jellyyoyo { background-image: url('jellyyoyo.png'); } #jquery { background-image: url('jquery.png'); } #flycan { background-image: url('flycan.png'); } #menuMask { position: absolute; z-index: 10000; display: block; left: 0; } .bhr { clear: both; height: 15px; z-index: 200; margin: 0 auto; background-color: #000; } |
這邊要注意一下,為了方便等下程式的存取控制,因此筆者就把圖片的檔名設成跟連結的 id 一樣,然後遮罩用的黑色圖片也只是多加了個 _black 字樣而已。這邊雖然是把每個選單圖片都拆開來,但如果要改成一張大圖也是可以,只是要控制好 background-position 就好。
看一下圖片的寬高:

因為我們的遮罩比一般的大上一點,因此等一下程式中要做一點微調的設定,這樣才不會看起來怪怪的。若沒問題的話,就來看 jQuery 的部份囉!
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 | // 避免無法正確取得選單圖片的寬高 // 因此動作延遲到 window.onload $(window).load(function(){ // 先取得選單的連結及找出 .selected 的選項 // 再取得用來當遮罩的 #menuMask // 因為遮罩圖片比原來選單圖片大,所以設定要顯示的寬高及位置差距 var _menu = $('#menu li>a'), _target = $(_menu).filter('.selected'), _menuMask = $('#menuMask'), _maskHeight = 10, _diffHeight = 8, _maskWidth = 5, _diffWidth = 5; // 如果沒有 .selected 的選項就預設第一個 if(_target.length<=0){ _target = $(_menu).eq(0); } // 圖片預載 _menu.each(function(){ $('<img />').attr('src', $(this).attr('id')+'_black.png').hide().appendTo('body'); }); // 當選單被點擊時.. _menu.click(function(){ // 先移除上一個有 .selected 的超連結 $('.selected').removeClass('selected'); // 把點擊到的項目加上 .selected var _this = $(this).addClass('selected'), _link = _this.attr('href'); // 更換選單的背景圖片及移動選單到該選項上 // 如果選項有連結時,則會在動畫移動完後來轉址 _menuMask.css({ backgroundImage: 'url('+_this.attr('id')+'_black.png)' }).stop().animate({ width: $(this).width() + _maskWidth, height: $(this).height() + _maskHeight, top: $(this).offset().top - _diffHeight, left: $(this).offset().left - _diffWidth }, function(){ // 如果有網址 if(!!_link){ // 如果有 target var _targetAttr = _this.attr('target'); if(!!_targetAttr){ // target = '_blank' 則開新窗 if(_targetAttr.toLowerCase()=='_blank'){ open(_link); }else{ // 連結開在指定的 target id 上 $('#'+_targetAttr).attr('src', _link); } }else{ location = _link; } } }); return false; }).focus(function(){ $(this).blur(); }); // 當瀏覽器尺寸改變時也要重新移動位置 $(window).resize(function () { moveMenu($(_menu).filter('.selected')); }); // 移動遮罩到指定的選項上面 function moveMenu(obj){ _menuMask.css({ width: obj.width() + _maskWidth, height: obj.height() + _maskHeight, top: obj.offset().top - _diffHeight, left: obj.offset().left - _diffWidth, backgroundImage: 'url('+obj.attr('id')+'_black.png)' }); } // 網頁載入後先移動遮罩 moveMenu(_target); }); |
一開始網頁載入後,如果連結有 .selected 的 className 時,則會把遮罩移到該選項上;反之若都沒有時,則把它移到第一個選項上面。因此,各位若有多個頁面時,就要一一的設定一下這樣的 .selected,不然就是要變更一下程式的判斷才行。
到這邊就完成整個山寨選單的製作了,讓我們看一下畫面及效果吧:

是不是給它有 9 成以上的相似度了呢!再特別說明一點,HTC 網站的 Flash 選單是當使用者點某一選項時,遮罩內容會馬上就變更,然後會移動到所點選的選項上面後再啟動連結的效果。因此筆者也把這功能加到我們的範例中,所以仔細注意一下整個移動的動作唷!
有上過 jQuery 課程的同學可以對照一下講義範例 5-13,做法及原理是一樣的!
更新:
2009-09-17
加入圖片預載功能
2010-01-18
加入連結開啟新窗及指定在 iframe
2009-09-17
加入圖片預載功能
2010-01-18
加入連結開啟新窗及指定在 iframe
範例瀏覽:
http://demonstration.abgne.tw/jquery/0008/0008.html
http://demonstration.abgne.tw/jquery/0008/0008_home.html(有連結效果)
相關連結
推薦內容


2009-09-17 15:25:37
沙潑沙潑~~
對了~~男丁版大~
第一次執行時好像會出現點一下等圖載完才會顯示~~
可以先把按到中圖片先作預載嗎?
2009-09-17 17:00:42
圖片預載的功能已經加進去囉..!!
各位再試看看有沒有給它順下去~~
2009-11-04 16:29:19
南丁老師。我整個網頁都抓下來,改了js連結
還是不能用。要怎麼樣另存下來?
2009-11-04 17:27:57
唔~把你有問題的範例檔案上傳或是寄來看看
不然只有這樣的描述很難知道問題..XD
2009-11-06 01:13:51
男丁版大,我用了
var $j = jQuery.noConflict();
然後將所有你script的$符號改成$j
但效果沒有了,不知是那裏弄錯 ><
2009-11-06 09:48:00
要有 sample 才知道你是錯在那..
該行的所在位置會有影響的
2009-12-16 10:02:49
老師您好,如果我要把選單滑動的效果改成用 mouseover ,click 連結之後,可以出現下拉選單。需要改哪些地方呢?
現在我是把 "_menu.click(function(){" 這一段改成 "_menu.mouseover(function(){"
,但是這樣會mouseover的地方就會直接連結,沒辦法再讓我 click
2009-12-16 10:17:08
因為原本我程式是在 click 時就把選單移到該選項後並連結到指定的網址..
現在就算改成 mouseover 時也是會有連結的效果..
所以你要把我範例程式的第40-44行的連結部份拿掉...把它寫在你的 click 事件中
2010-01-13 23:06:45
老師您好,請教一下,如果連結我想要另開新視窗的話要如何修改呀(或者網頁多了一個內置框架,想讓連結顯示在框架內)
2010-01-14 23:01:07
只要在超連結中加入 target 屬性後指定要開新頁還是框架 id 即可。
2010-01-18 10:46:56
謝謝大大的指導
但我加了 target 屬性,但沒用說
Yahoo
又要麻煩大大指教了~
2010-01-18 11:11:27
不好意思..請把 htcmenu.js 中的第 41~43 行改用下面的程式:
2010-01-18 12:04:43
謝謝老師
剛才測試了開新視窗OK了
但如果是內框的話無法使用說
a target="I1" href="html/Home.htm" id="Home">Hone</a
他不會顯示在內框,而是另開一個新視窗
老師在順便請教一個問題
backgroundImage: 'url('+_this.attr("id")+'_black.png)
如果我有建立了一個資料夾"jpg" 如果修改語法,當我點選時他會至資料夾載入圖片
謝謝,以上二個問題請教
2010-01-18 12:38:33
你所謂的內框是指 iframe 嗎..?它的 id 是叫 I1 嗎?
如果你選單圖片是放在資料夾中的話..那就是把
改成
2010-01-18 12:47:38
嗯~內置框架 iframe ID叫I1
2010-01-18 12:49:25
有範例網頁可參考看看嗎?
2010-01-18 12:58:39
附上網頁
http://lineage543.sg1006.myweb.hinet.net/test/
2010-01-18 13:00:15
幫 iframe 多加一個 id="I1" 後試試
2010-01-18 13:16:17
老師~抱歉我不太懂您說的意思
原先就有這行了iframe name="I1" height="98%" width="98%" src="html/Home.htm"
您的意思是把 iframe name="I1" 改為 iframe id="I1" 因為試了好像都沒有用
2010-01-18 13:20:24
仔細看剛剛回覆的的程式碼...
你用到的是舊版的..不支援 iframe......如果替換最新的 code 之後..
一樣是把 iframe 多加一個跟 name 同值的 id
2010-01-18 14:48:25
大大~真不好意思
小弟不才,做了一些修改後又有新問題出現
我方便寄檔給你幫忙看看嗎
2010-01-18 14:51:03
Mail 資訊在留言區塊的上方就有..
2010-01-20 13:22:40
老師您好,請教一下,此特效在Google瀏覽器下無法正常說。
不知道有沒有辦法改善,謝謝。
2010-01-20 13:27:35
那邊不正常..?我試文章中的範例是ok的...
2010-01-20 14:41:09
謝謝老師,我使用原檔測也OK,我知道問題出現在那了@@
我只是把選單下方那排黑色拿掉後在Google下就無法使用(但IE正常)
2010-01-20 14:48:39
黑色其實只是一條 bar 而已..應該是不影響程式的..
可以的話..給個問題範例看看
2010-01-20 21:11:20
老師您好,已經mail給您了~
2010-06-19 11:27:15
老師您好
我想將HTC選單與lightbox做結合
可是開啟lightbox的圖片時
HTC選單會顯示在lightbox上方
請問要怎樣改在下方呢?
範例:http://cid-3a078afd3bc4ed0f.office.live.com/self.aspx/.Documents/test.rar
※lightbox在平面設計選單下
2010-06-19 18:54:47
你可以先把 #menuMask 及 .bhr 的 z-index 調小一點後試看看。
例如 #menuMask 的 z-index 設為 50, .bhr 的設成 20
2010-07-26 14:00:55
請問板大圖片預載的功能是要放在
// 圖片預載
_menu.each(function(){
$(").attr('src', $(this).attr('id')+'_black.png').hide().appendTo('body');
});
的那個位子...試好久都沒成功><"
我圖片放在images...
2010-07-26 14:24:46
圖片預載要放在哪個位子??
2010-07-26 21:31:44
你檔名也是一般跟 _blank 的區別嗎?
2010-07-26 23:52:51
對!
有_black
放在images裡面
2010-07-27 14:13:25
你的問題是沒預載還是選單沒變圖片?
2010-08-03 15:20:39
點選該按鈕,會跑去該頁!可是整個頁面會重新整理,按鈕會跑去"首頁"那選項(黑色),請問程式碼內要怎麼下?
2010-08-04 11:07:37
在每個頁面的該選項上多加個 selected 的 class
2010-08-19 15:57:19
點選之後,原來覆蓋黑色部分,是否連結一樣可以再次點選~
2010-08-19 22:15:12
那你要針對 _menuMask 再加上 click 事件
2010-08-20 09:36:47
有demo可以示範一下嗎~感恩^^
2010-08-21 12:14:18
有空時我會補上..也許你可以自己試試然後提出問題一起討論:D
2010-08-26 16:32:42
小弟愚笨~試了好久還是用不出來ㄋㄟ
2010-08-27 16:27:42
你要針對遮罩做 click 事件..然後點了之後找出原始的鈕來做動作