一、開篇
在研究CS08的時候,看到後台管理的Dashboard滑動按鈕做得很漂亮,於是自己就動手寫了一個,在這裡與大家分享。菜單展開可以是滑鼠點擊按鈕,也可以是滑鼠移動到按鈕上,在這裡先介紹滑鼠點擊的這種菜單。
二、原理
基本原理很簡單,就是將需要滑動的菜單放在一個overflow為hidden的容器裡,然後控制功能表相對於容器的top屬性,實現下拉的效果。
但是實際上也沒這麼簡單,因為要遇到很多問題,比如容器的大小如何控制、容器如何確定位置、容器應該何時出現(如果容器一直存在,則會擋住容器下面的元素)。這些問題是怎麼解決的,在下一部分的代碼裡會有注釋說明。在這裡說明一下大概的原理:
1、首先在頁面載入時,要給菜單加上一個外框,就是中的menuContainer,這個框的作用就是遮擋menu。頁面載入後,讓menu的visibility為hidden,這時使用者看不到菜單,但是我們可以獲得menu的長和寬,將這個值賦給menuContainer的長和寬(此時menuContainer的display為block,要不然根本就沒法賦值),然後將menuContainer的display設定為none。
2、當滑鼠點擊按鈕時,根據按鈕的位置來確定下拉式功能表的位置,將menuContainer的display設定為block後,就可以控制menu的top屬性(menu的position為absolute)實現滑動。
3、在滑動的過程當中,不能有按鈕的事件或者document關於菜單的事件被註冊,這樣會影響滑動的過程。所以滑動之前刪除註冊,滑動結束過後重新註冊事件。
4、當菜單展開的時候,點擊按鈕時菜單會收回,這裡巧妙的用到了事件的冒泡。菜單展開的時候,根據if(isOpened)return;這一句來看,就像點擊按鈕不起作用一樣,點擊按鈕的事件會冒泡到document,而此時document恰好註冊有關閉菜單的方法,從而實現了再次點擊按鈕關閉菜單的目的。
三、代碼
注意:這裡用到了關於事件的一個簡單架構和幾個其他函數,具體的可以下載樣本後看源檔案。 也可以看我之前寫的部落格文章進行瞭解。
SlideMenu
function SlideMenu(oBtn,oMenu){
var btn = oBtn;
var menu = oMenu;
var isOpened = false;
//為下拉式功能表添加外框
var menuContainer = document.createElement("div");
menu = menu.parentNode.removeChild(menu);
menuContainer.appendChild(menu);
document.body.appendChild(menuContainer);
//設定外框必要的樣式
menuContainer.style.display = 'block';
menuContainer.style.visibility = 'visible';
menuContainer.style.overflow = 'hidden';
menuContainer.style.position = 'absolute';
// 設定下拉式功能表的樣式
menu.style.position = 'absolute';
menu.style.overflow = 'visible';
menu.style.display = 'block';
menu.style.visibility = 'hidden';// 使用者既看不到下拉式功能表 又可以擷取菜單的寬和高
// 獲得下拉式功能表的寬和高
var menuWidth = menu.offsetWidth;
var menuHeight = menu.offsetHeight;
//設定下拉式功能表容器的寬和高
menuContainer.style.width = menuWidth;
menuContainer.style.height = menuHeight;
// 將下拉式功能表容器隱藏
menuContainer.style.display = 'none';
var btnClick = function(){
// 如果已經是展開的話 就不做響應
// 而是通過事件冒泡轉交給document的click處理
// 這是會關閉菜單
if(isOpened)
return;
// 如果正在展開的過程中 又點擊了按鈕的話 就會響應很多次
// 這樣就可以限制在展開的過程當中多次點擊按鈕
btn.onclick = null;
// 將下拉容器設定為可見 此時下拉式功能表為display:block;visibility:hidden;
menuContainer.style.display = 'block';
// 設定下拉容器的位置
var pos = GetPosition(btn);
menuContainer.style.left = pos.x + 'px';
menuContainer.style.top = (pos.y + btn.offsetHeight) + 'px';
// 設定下拉式功能表的屬性
menu.style.left = '0px';
menu.style.top = -menuHeight + 'px';
menu.style.visibility = 'visible';
BufferMove('document.getElementById("' + menu.id + '").style.top',-menuHeight,0,30,1,fnCallback);
function fnCallback(){
oEventUtil.addEventHandler(document,"click",docClick);
btn.onclick = btnClick;
isOpened = true;
}
}
btn.onclick = btnClick;
var docClick = function(){
oEvent = oEventUtil.getEvent();
//防止右鍵點擊
if(oEvent.button == 2)
return;
oEventUtil.removeEventHandler(document,"click",docClick);
BufferMove('document.getElementById("' + menu.id + '").style.top',0,-menuHeight,30,1,fnCallback);
function fnCallback(){
menuContainer.style.display = 'none';
isOpened = false;
}
}
}
這是菜單類的主要代碼,下面是使用方法
window.onload = function(){
new SlideMenu($("btn1"),$("menu1"));
}
即在執行個體化時傳入兩個對象到建構函式,前一個參數是功能表按鈕對象,後一個參數是需要展開的菜單的對象。
四、下載
點此下載樣本