Web組件流暢拖動效果
拖動效果,可以形象的幫助用戶處理一些問題,比如Windows刪除文件,只需將文件拖動至回收站即可。比起右鍵顯得更形象,我覺得更好玩一點^_^。當然,在其他許多方面,其實也有用到拖動效果,只是他們不是那么明顯,以至于我們不容易覺察到。我是自娛自樂,寫一個Web MusicPlayer的時候開始對拖動有所構思,因為需要做個左右一定范圍內拖動的按鈕,來改變Music文件的播放進度。
不多說了,下面我們來進入本篇的正題。
需要的組件:我們先來理一下簡化后的拖動模型,只需要一個簡單的于body中一個普通的div。他的大小應該適中,這樣在看其相對鼠標運動時更加清晰。
拖動觸發(fā)的事件:1.mousedown 2.mousemove 3.mouseup
拖動過程:鼠標左鍵在div上單擊觸發(fā)mousedown事件,在mousedown事件之后,鼠標開始拖動動作,觸發(fā)mousemove事件,注意,此時div應該跟隨鼠標在body上移動。這就牽扯到拖動的組件div的left(左支撐),以及top(上支撐)的該變量。(當然也可以用right和bottom來反映,效果一樣)。要獲取鼠標移動情況,在mousedown事件(設為事件ed)之后,獲取鼠標屏幕位置(ed.clientX,ed.clientY);鼠標移動后mousemove事件(設為事件em)獲取鼠標位置(em.clientX,em.clientY);則鼠標移動在X,Y方向的分量也是div將要移動的分量為(em.clientX,em.clientY)-(ed.clientX,ed.clientY)=(em.clientX-ed.clientX,em.clientY-ed.clientY);注意到得的值可能有負值情況,這種情況是不影響的。因為,如果我們假設鼠標相對(ed.clientX,ed.clientY)向右下移動至(em.clientX,em.clientY),若其中出現負值,相應的加號接變成了減號,也就是移動方向為假設方向的反方向,有實際意義,并不影響效果。現在,開始移動我們唯一的div,(在實際運行中,兩者移動幾乎是同步的,這里分開來說,只是便于理解),由上文我們知道div應該跟隨鼠標向假設的方向右下移動(em.clientX-ed.clientX,em.clientY-ed.clientY);要在js中獲取組件div的left和top即初始位置(d.offsetLeft,d.offsetTop)(這里d=document.getElementById('div');),則只需在mousemove事件觸發(fā)時,對div的left和top重新賦值即可跟隨鼠標移動,所以移動后的div位置為(d.offsetLeft,d.offsetTop)+(em.clientX-ed.clientX,em.clientY-ed.clientY)=(d.offsetLeft+em.clientX-ed.clientX,d.offsetTop+em.clientY-ed.clientY);這樣,我們整個移動的過程就完成。
但是如果所有的事件監(jiān)聽器全部放在待拖動div組件上,你會發(fā)現這個div很“脆弱”,慢慢拖動div中心完全沒事,但是,當點擊div邊緣拖動,或者拖動速度較快時,你會發(fā)現我們的辛辛苦苦做出的div玩去了,跑丟了。Q~Q。這是因為當mousemove觸發(fā)時,div跟隨鼠標移動,并非是完全同步的,他們之間是有很小的延時的。當我們拖動速度很快的時候,鼠標跑出了div的“領域”,而我們的mousedown是加在div上的,現在鼠標已經不在領域內,自然也就停下來了。鼠標和div分道揚鑣。要避免這個問題,也就是當鼠標在div外移動時,div依然艱難的保持與鼠標同步運動。即,mousedown依然放在div上,而mousemove放在我們的最大的容器body上,這樣,當鼠標位于div外時,div依然追隨我們我行我素的鼠標。為了避免當移速過快時突然up鼠標左鍵情況(這時,我們鼠標即使沒有down左鍵,當鼠標進入div時,div依然追隨鼠標),mouseup也應該加在最大的容器body上,至此,我行我素的鼠標和至死不渝的div曲折的故事圓滿收尾。
理清了思路下面就開始愉快的代碼時間了。(為了粘貼方便,這里就不分開css,js了)
看一下效果http://dearvee.ccaeo.com/blog/move.html
2017-03-08 17:13:01
<!DOCTYPE html>
<html>
<head>
<title>move</title>
</head>
<style type="text/css">
.body_css{
width: 100%;
height: 100%;
position: absolute;
}
.div_css{
width: 100px;
height: 100px;
background-color: #0ff;
position: absolute;
left: 0px;
top: 0px;
color: #fff;
user-select:none;
}
</style>
<script type="text/javascript">
window.onload=function (){
var d = document.getElementById('div');
var b = document.getElementById('body');
d.addEventListener("mousedown", function(ed) {
var flag=true;
var dl=d.offsetLeft;
var dt=d.offsetTop;
b.addEventListener("mousemove",function(em){
if(flag){
d.style.left=dl+em.clientX-ed.clientX+"px";
d.style.top=dt+em.clientY-ed.clientY+"px";
}
});
b.addEventListener("mouseup",function(){
flag=false;
});
});
}
</script>
<body id="body" class="body_css">
<div id="div" class="div_css">你甩不掉我的<br>Q_Q</div>
</body>
</html>


浙公網安備 33010602011771號