先看看要拖動的層(類比視窗)的吧。
要實現的拖動效果:滑鼠左鍵在視窗上方的標題列上按下,同時移動滑鼠,視窗跟著移動。
視窗:
複製代碼 代碼如下:<div id="win">
<div id="win_header"></div>
</div>
一點準備工作:
要讓視窗能自由移動,那麼視窗的定位(position)應該採用絕對位置(absolute);
給視窗添加標題列,這裡使用一個放在視窗頂部的層實現,同時將標題列的滑鼠游標設定為拖動(move)形狀(在chrome中拖動的時候,游標會變成文字游標,鬆開滑鼠鍵後恢複)。 複製代碼 代碼如下:#win {
position:absolute;
width:480px;
height:320px;
background-color:#d4d4d4;
border: 1px solid #4d4d4d;
}
#win_header {
width:480px;
height:48px;
background-color:#4d4d4d;
cursor:move;
}
定義一個工具函數,用來擷取指定ID屬性的元素: 複製代碼 代碼如下:function $id(id) {
return document.getElementById(id);
}
定義一個瀏覽器核心標識isIE:
var isIE = (window.navigator.userAgent.indexOf("IE") == -1) ? false : true;
擷取到視窗元素及其標題列: 複製代碼 代碼如下:var win = $id("win");
var header = $id("win_header");
為了方便記錄滑鼠和視窗的位置資訊,建立一個位置: 複製代碼 代碼如下:var pos =function(x, y) {
this.x = x;
this.y = y;
};
給視窗設定一個初始位置(css的left值和top值)。
這裡不知道是為什麼,如果不使用js設定這兩個屬性,就取不到值,在CSS中指定了也不行。 複製代碼 代碼如下:var originalpos = new pos(20, 20);
在拖動視窗的過程中,需要記錄的值有:
滑鼠按下時滑鼠游標的位置 複製代碼 代碼如下:var oldmouse =new pos(0, 0);
滑鼠按下時視窗的位置
var oldpos = new pos(0, 0);
滑鼠移動時視窗的新的位置
var newpos = new pos(0, 0);
設定視窗的初始位置 複製代碼 代碼如下:win.style.left = originalpos.x + "px";
win.style.top = originalpos.y + "px";
又是因為瀏覽器的差異(IE和非IE),元素繫結事件處理函數的方法不同(IE使用attachEvent,非IE使用addEventListener),為了簡化事件綁定的操作,定義一個事件綁定函數: 複製代碼 代碼如下:function bind(ev, func) {
if(isIE) {
header.attachEvent("on" + ev, func);
} else {
header.addEventListener(ev, func, false);
}
}
在做好這些工作後,就可以開始處理滑鼠事件了。
在這個程式中,只希望滑鼠左鍵拖動視窗,其它鍵都不能,所以需要判斷是否是滑鼠左鍵按下。而這個判斷會在幾個函數中都使用到,所以提取出來到一個函數中,通過傳入的參數(滑鼠鍵值,即按下了哪個鍵)判斷。在這裡,需要注意瀏覽器間的差異:IE中滑鼠左鍵的值是1,而非IE中值是0. 複製代碼 代碼如下:function isLeftButton(btn) {
if(isIE) {
if(btn == 1)
return true;
else
return false;
} else {
if(btn == 0)
return true;
else
return false;
}
}
拖動動作是在按下滑鼠左鍵後移動來完成的。把這個動作分享開來,即是滑鼠先觸發了按下動作(mousedown),然後觸發了移動動作(mousemove)。為了判斷是否是真的在拖動還是只是滑鼠從視窗上經過,設定一個變數來記錄滑鼠按下的狀態:
var mousedown = false;
由於CSS中存在的相容性問題,這裡使用js來控制滑鼠移至上方在視窗標題列上面的時候的顏色變化。
懸浮 複製代碼 代碼如下:function over(e){
header.style.backgroundColor = "#5d5d5d";
}
離開 複製代碼 代碼如下:function out(e) {
header.style.backgroundColor = "#4d4d4d";
// 有時候滑鼠會在未鬆開的情況下離開視窗,
// 此時通過觸發滑鼠的鬆開事件來使視窗脫離滑鼠的控制
up(e);
}
按下
在按下事件中,需要先判斷是否按下的是滑鼠的左鍵;
若是才記錄滑鼠和視窗此時的位置,否則不記錄。 複製代碼 代碼如下:function down(e) {
e = e || event;
if(!isLeftButton(e.button))
return;
mousedown = true;
oldmouse.x = e.clientX;
oldmouse.y = e.clientY;
oldpos.x = parseInt(win.style.left.replace("px", ""));
oldpos.y = parseInt(win.style.top.replace("px", ""));
}
鬆開 複製代碼 代碼如下:function up(e) {
if(!isLeftButton(e.button))
return;
mousedown = false;
}
移動
這裡就涉及到滑鼠的兩個事件:
按下和移動。若且唯若滑鼠左鍵按下時,移動動作才有效。
視窗的新位置,是由滑鼠在拖動狀態下的移動距離(X和Y的距離)決定的。即:
新的滑鼠位置送去按下左鍵時記錄下的位置,得到一個距離,然後將視窗的位置加上滑鼠移動的距離得到視窗的新位置。 複製代碼 代碼如下:function move(e) {
if(!isLeftButton(e.button))
return;
if(mousedown) {
e =e || event;
newpos.x = e.clientX - oldmouse.x;
newpos.y = e.clientY - oldmouse.y
win.style.left = (oldpos.x + newpos.x) + "px";
win.style.top = (oldpos.y + newpos.y) + "px";
}
}
事件處理都寫好了,最後來給元素繫結上吧,阿門! 複製代碼 代碼如下:bind("mouseover", over);
bind("mouseenter", over);
bind("mouseout", out);
bind("mouseleave", out);
bind("blur", out);
bind("mousedown", down);
bind("mouseup", up);
bind("mousemove", move);
不過在FF中的拖動有問題,只能第一次正常拖動,後面就有點亂了!