JS實現QQ面板-拖曳效果
實現的功能是將整個QQ面板在特定區域點選滑鼠按下移動,面板會隨著游標移動而移動,這可以稱為滑鼠跟隨效果,也叫拖曳效果。
首先是確定HTML結構,定義一個父元素模擬整個QQ面板,設定標題區域用於JS選中進行拖曳。
<div class="loginPanel" id="loginPanel">
<div id="title"></div>
</div>
CSS樣式,這裡有一個需要注意的地方就是面板會跟隨滑鼠移動,涉及到座標的問題就應該在該元素上設定絕對定位。
.loginPanel {width: 380px;height: 247px;left: 400px;top: 120px;position: absolute;border: 1px solid #ccc;background: #f6f6f6;border-radius: 10px;box-shadow: 0 0 8px #000;} #title {background-color: #adc;width: 200px;height: 44px;cursor: move;position: absolute;top: 10px;left: 98px;}
JS部分,我們來分析一下來確定完成的思路,第一步首要的就是會想到既然是要在特定 title 區域選中滑鼠按下移動,那麼我們就要來獲取到這個 title 元素,獲取之後呢?想不到了,做一步想一步吧。
window.onload=drag;
function drag(){
var oTitle=document.getElementById("title");
oTitle.onmousedown=fnDown;
}
title 元素獲取到之後,是進行滑鼠按下移動的,這就用到了onmousedown事件,將其封裝成一個函式,來具體實現。這裡還是不能忘了滑鼠拖曳效果的原理:面板跟隨游標位置的移動而移動。我們需要用到滑鼠座標,又因為滑鼠事件都是在瀏覽器視窗中的特定位置上發生的。這個位置資訊儲存在實踐的clientX和clinetY屬性中。它們的值表示事件發生時滑鼠指標在視口中的水平和垂直座標,不包括頁面滾動的距離。之前有提過QQ面板元素需要絕對定位,那麼設定它的移動就是設定top / left 值。
function fnDown(){
var oDrag=document.getElementById('loginPanel');
document.onmousemove=function(event){
event = event || window.event;
oDrag.style.left=event.clientX+"px";
oDrag.style.top=event.clientY+"px";
}
}
去瀏覽器中試驗一下,有著很明顯的不舒服的地方,也不能算bug,就是使用者體驗不好,每次按下標題中任一個區域拖動面板,滑鼠總會自動跑到整個面板的左上角。這是因為對整個面板的絕對定位是按照左上角那個點進行定位的,也就是說滑鼠移動到哪裡,最後是面板的左上角跟隨到哪裡。這顯然不是我們想要的,我們需要的是在標題中任一區域按下,滑鼠移動到哪裡,之前按下的地方就出現在哪裡。
我們知道了問題所在,那麼該如何解決呢?之前是因為預設的面板左上角跟隨滑鼠,那我們讓按下的地方跟隨滑鼠不就好了嘛,所有現在就得確定我們在title 區域中按下的位置的座標。通過一幅圖來形象的瞭解。
整個外框就相當於瀏覽器邊框,紅色的點就是我們滑鼠按下的位置,那這個點相對於QQ面板的位置資訊可以通過clientX/Y - offsetLeft/Top 計算得到。這樣的話,之前寫的fnDown函式就不對了呀,修改如下。其中,將滑鼠移動事件封裝成函式。
function fnDown(event){
event = event || window.event;
var oDrag=document.getElementById('loginPanel'),
// 游標按下時游標和麵板之間的距離
disX=event.clientX-oDrag.offsetLeft,
disY=event.clientY-oDrag.offsetTop;
// 移動
document.onmousemove=function(event){
event = event || window.event;
fnMove(event,disX,disY);
}
}
fnMove函式接受三個引數,事件物件,滑鼠點選下相對於面板的上左距離。我們是知道滑鼠移動後是面板的左上角跟隨滑鼠,現在已經有了滑鼠點選下相對於面板的上左距離的值,那麼就可以在原有的左上角座標增加或減去這個值,這就能夠實現滑鼠在哪裡按下,移動之後就在哪裡出現。表述能力真的欠佳,感覺說的亂繞繞的,還是程式碼清晰。
function fnMove(e,posX,posY){
var oDrag=document.getElementById('loginPanel'),
l=e.clientX-posX,
t=e.clientY-posY,
oDrag.style.left=l+'px';
oDrag.style.top=t+'px';
}
以上就很好的解決了之前那個使用者體驗不好的地方。那會不會還存在一些問題?顯而易見,一定會有的。我們拖動面板,有時候在瀏覽器邊界時候會一部分移出可視視窗,這也很糟糕呀,譬如一不小心把關閉按鈕啊、登入按鈕啊、輸入框啊這些部分移除可視視窗,就很不好操作了,還需要使用者再把面板移回來,使用者體驗絕對是不好的。這時就需要我們來設定一個範圍,來規定面板可移動的區域。這個區域很明顯就是可視視窗的大小減去面板的大小,這剩下的區域就是面板能夠盡情移動的範圍了。我們需要在fnMove函式基礎上增添。
function fnMove(e,posX,posY){
var oDrag=document.getElementById('loginPanel'),
l=e.clientX-posX,
t=e.clientY-posY,
winW=document.documentElement.clientWidth || document.body.clientWidth, //可視視窗的寬
winH=document.documentElement.clientHeight || document.body.clientHeight, //可視視窗的高
maxW=winW-oDrag.offsetWidth, //可移動的範圍的寬
maxH=winH-oDrag.offsetHeight; //可移動的範圍的高
if(l<0){
l=0;
}else if(l>maxW){
l=maxW;
}
if(t<0){
t=10;
}else if(t>maxH){
t=maxH;
}
oDrag.style.left=l+'px';
oDrag.style.top=t+'px';
}
現在就完成了滑鼠移動拖曳的效果,滑鼠按下之後就可以拖動面板跟著滑鼠移動,嗯,一直移動不帶停的。我們必須要有一個滑鼠釋放的事件,來停止當前的動作。這就用到了onmouseup事件,這個事件的發生是處於整個文件中的。所謂停止當前的動作就是要解除安裝之前滑鼠移動事件,也要解除安裝當前這個滑鼠釋放事件。當然這是發生在fnDown函式中。
document.onmouseup=function(){
document.onmousemove=null;
document.onmouseup=null;
}
就此,完美的實現了拖曳效果。需要注意的是關於瀏覽器中座標的計算。