一起來(lái)寫段JS drag拖動(dòng)代碼
更新時(shí)間:2010年12月09日 18:31:37 作者:
記得幾年前剛接觸前端的時(shí)候,覺(jué)得能在網(wǎng)頁(yè)上拖移元素是一件很爽的事,能寫一段這樣的代碼是件很了不起的事情,于是乎google,baidu蠻多代碼來(lái)學(xué)習(xí),大致明白了思路,總結(jié)如下
1、為要被拖移三個(gè)事件,onmousedown,onmousemove,onmouseup
2、在onmousemove事件中來(lái)處理被拖移元素的位置的變化,其實(shí)說(shuō)白了元素要移動(dòng)的距離就是鼠標(biāo)兩次移動(dòng)之間的距離。
3、其中還包括setCapture,releaseCapture,目的就是為了被搬移的元素始終能擁有焦點(diǎn)。
以前大致就是以前的認(rèn)識(shí),可以參見 JS拖動(dòng)技術(shù)--- 關(guān)于setCapture 這個(gè)實(shí)現(xiàn),后來(lái)隨著工作要求的提高,做的工作都是要跨瀏覽器的,所以就重新構(gòu)思并參考一些開源代碼做了實(shí)現(xiàn)。
現(xiàn)在大致思路可分析為以下幾步,我一一為您展現(xiàn)。
1、 我們是為了拖移而搬移嗎?當(dāng)然不是,如google地圖,當(dāng)每次搬移后他的目的是為了計(jì)算當(dāng)前空間坐標(biāo)來(lái)加載地理信息。所以我這里設(shè)計(jì)了幾個(gè)常見事件。以下是事件列表
onDragStart :元素發(fā)生拖移時(shí),如果注冊(cè)該事件,觸發(fā)時(shí)會(huì)接收到兩個(gè)參數(shù)x,y分別為被搬移元素發(fā)生拖移時(shí)的坐標(biāo)
onDrag : 元素拖移過(guò)程中,如果注冊(cè)該事件,觸發(fā)時(shí)會(huì)接收到兩個(gè)參數(shù)nx,ny拖移過(guò)程中坐標(biāo)發(fā)生的偏移量
onDragEnd :元素發(fā)生結(jié)束時(shí),如果注冊(cè)該事件,觸發(fā)時(shí)會(huì)接收到兩個(gè)參數(shù)x,y分別為被搬移元素的當(dāng)前坐標(biāo)
2、 onmousedown事件應(yīng)該綁定給誰(shuí)?以前我都是綁定給被拖移元素的,后來(lái)發(fā)現(xiàn)很不靈活,現(xiàn)在設(shè)計(jì)為可綁定給任意不相關(guān)的元素同時(shí)實(shí)現(xiàn)該元素的拖動(dòng)。
3、 如何來(lái)實(shí)現(xiàn)元素搬移過(guò)程中一直擁有焦點(diǎn)?因?yàn)橐鐬g覽器,所以就不再用setCapture之類的方法,這里換種思維,為什么元素元素搬移過(guò)程中沒(méi)有了焦點(diǎn)呢,主要是我們把onmousemove事件注冊(cè)到了被拖移的元素上,而這并不是必需的,所以當(dāng)元素觸發(fā)onmousedown事件后,我把onmousemove、onmouseup事件直接注冊(cè)到document上,這樣鼠標(biāo)移到哪都會(huì)有焦點(diǎn)。
說(shuō)完了這么多,直接看代碼結(jié)構(gòu)吧!
Drag = {
obj: null,
init: function (options) {
options.handler.onmousedown = this.start;
options.handler.root = options.root || options.handler;
var root = options.handler.root;
root.onDragStart = options.dragStart || new Function();
root.onDrag = options.onDrag || new Function();
root.onDragEnd = options.onDragEnd || new Function();
},
start: function (e) {//此時(shí)的this是handler
var obj = Drag.obj = this;
obj.style.cursor = 'move';
e = e || Drag.fixEvent(window.event);
ex = e.pageX;
ey = e.pageY;
obj.lastMouseX = ex;
obj.lastMouseY = ey;
var x = obj.root.offsetLeft;
var y = obj.root..offsetTop;
obj.root.style.left = x + "px";
obj.root.style.top = y + "px";
document.onmouseup = Drag.end;
document.onmousemove = Drag.drag;
obj.root.onDragStart(x, y);
},
drag: function (e) {
e = e || Drag.fixEvent(window.event);
ex = e.pageX;
ey = e.pageY;
var root = Drag.obj.root;
var x = root.style.left ? parseInt(root.style.left) : 0;
var y = root.style.top ? parseInt(root.style.top) : 0;
var nx = ex - Drag.obj.lastMouseX + x;
var ny = ey - Drag.obj.lastMouseY + y;
root.style.left = nx + "px";
root.style.top = ny + "px";
Drag.obj.root.onDrag(nx, ny);
Drag.obj.lastMouseX = ex;
Drag.obj.lastMouseY = ey;
},
end: function (e) {
var x = Drag.obj.root.style.left ? parseInt(Drag.obj.root.style.left) : 0;
var y = Drag.obj.root.style.top ? parseInt(Drag.obj.root.style.top) : 0;
Drag.obj.root.onDragEnd(x, y);
document.onmousemove = null;
document.onmouseup = null;
Drag.obj = null;
},
fixEvent: function (e) {
e.pageX = e.clientX + document.documentElement.scrollLeft;
e.pageY = e.clientY + document.documentElement.scrollTop;
return e;
}
}
上面init主要處理一些初如化工作,如記錄onDragStart、onDrag、onDragEnd三個(gè)事件, handler為處理拖動(dòng)事件的那個(gè)元素,root為被拖動(dòng)的元素。
當(dāng)在handler上點(diǎn)擊后觸發(fā)Drag.start方法,Drag.start主要為記錄住鼠標(biāo)相對(duì)整個(gè)頁(yè)面的位置;給document注冊(cè)onmouseup、onmousemove事件,及觸發(fā)onDragStart事件。
Drag.drag方法也很簡(jiǎn)單,主要作用就是更新被搬移元素位置,同時(shí)記錄住鼠標(biāo)相對(duì)整個(gè)頁(yè)面的位置。
Drag.end方法就更簡(jiǎn)單了,就是做一些收尾工作。
最后給大家附段使用的代碼吧,祝大家學(xué)習(xí)愉快!
Drag.init({
handler: document.getElementById("handler"),
root:document.getElementById("root");
});
<div id="root">
<h2 id="handler"></h2>
</div>
2、在onmousemove事件中來(lái)處理被拖移元素的位置的變化,其實(shí)說(shuō)白了元素要移動(dòng)的距離就是鼠標(biāo)兩次移動(dòng)之間的距離。
3、其中還包括setCapture,releaseCapture,目的就是為了被搬移的元素始終能擁有焦點(diǎn)。
以前大致就是以前的認(rèn)識(shí),可以參見 JS拖動(dòng)技術(shù)--- 關(guān)于setCapture 這個(gè)實(shí)現(xiàn),后來(lái)隨著工作要求的提高,做的工作都是要跨瀏覽器的,所以就重新構(gòu)思并參考一些開源代碼做了實(shí)現(xiàn)。
現(xiàn)在大致思路可分析為以下幾步,我一一為您展現(xiàn)。
1、 我們是為了拖移而搬移嗎?當(dāng)然不是,如google地圖,當(dāng)每次搬移后他的目的是為了計(jì)算當(dāng)前空間坐標(biāo)來(lái)加載地理信息。所以我這里設(shè)計(jì)了幾個(gè)常見事件。以下是事件列表
onDragStart :元素發(fā)生拖移時(shí),如果注冊(cè)該事件,觸發(fā)時(shí)會(huì)接收到兩個(gè)參數(shù)x,y分別為被搬移元素發(fā)生拖移時(shí)的坐標(biāo)
onDrag : 元素拖移過(guò)程中,如果注冊(cè)該事件,觸發(fā)時(shí)會(huì)接收到兩個(gè)參數(shù)nx,ny拖移過(guò)程中坐標(biāo)發(fā)生的偏移量
onDragEnd :元素發(fā)生結(jié)束時(shí),如果注冊(cè)該事件,觸發(fā)時(shí)會(huì)接收到兩個(gè)參數(shù)x,y分別為被搬移元素的當(dāng)前坐標(biāo)
2、 onmousedown事件應(yīng)該綁定給誰(shuí)?以前我都是綁定給被拖移元素的,后來(lái)發(fā)現(xiàn)很不靈活,現(xiàn)在設(shè)計(jì)為可綁定給任意不相關(guān)的元素同時(shí)實(shí)現(xiàn)該元素的拖動(dòng)。
3、 如何來(lái)實(shí)現(xiàn)元素搬移過(guò)程中一直擁有焦點(diǎn)?因?yàn)橐鐬g覽器,所以就不再用setCapture之類的方法,這里換種思維,為什么元素元素搬移過(guò)程中沒(méi)有了焦點(diǎn)呢,主要是我們把onmousemove事件注冊(cè)到了被拖移的元素上,而這并不是必需的,所以當(dāng)元素觸發(fā)onmousedown事件后,我把onmousemove、onmouseup事件直接注冊(cè)到document上,這樣鼠標(biāo)移到哪都會(huì)有焦點(diǎn)。
說(shuō)完了這么多,直接看代碼結(jié)構(gòu)吧!
復(fù)制代碼 代碼如下:
Drag = {
obj: null,
init: function (options) {
options.handler.onmousedown = this.start;
options.handler.root = options.root || options.handler;
var root = options.handler.root;
root.onDragStart = options.dragStart || new Function();
root.onDrag = options.onDrag || new Function();
root.onDragEnd = options.onDragEnd || new Function();
},
start: function (e) {//此時(shí)的this是handler
var obj = Drag.obj = this;
obj.style.cursor = 'move';
e = e || Drag.fixEvent(window.event);
ex = e.pageX;
ey = e.pageY;
obj.lastMouseX = ex;
obj.lastMouseY = ey;
var x = obj.root.offsetLeft;
var y = obj.root..offsetTop;
obj.root.style.left = x + "px";
obj.root.style.top = y + "px";
document.onmouseup = Drag.end;
document.onmousemove = Drag.drag;
obj.root.onDragStart(x, y);
},
drag: function (e) {
e = e || Drag.fixEvent(window.event);
ex = e.pageX;
ey = e.pageY;
var root = Drag.obj.root;
var x = root.style.left ? parseInt(root.style.left) : 0;
var y = root.style.top ? parseInt(root.style.top) : 0;
var nx = ex - Drag.obj.lastMouseX + x;
var ny = ey - Drag.obj.lastMouseY + y;
root.style.left = nx + "px";
root.style.top = ny + "px";
Drag.obj.root.onDrag(nx, ny);
Drag.obj.lastMouseX = ex;
Drag.obj.lastMouseY = ey;
},
end: function (e) {
var x = Drag.obj.root.style.left ? parseInt(Drag.obj.root.style.left) : 0;
var y = Drag.obj.root.style.top ? parseInt(Drag.obj.root.style.top) : 0;
Drag.obj.root.onDragEnd(x, y);
document.onmousemove = null;
document.onmouseup = null;
Drag.obj = null;
},
fixEvent: function (e) {
e.pageX = e.clientX + document.documentElement.scrollLeft;
e.pageY = e.clientY + document.documentElement.scrollTop;
return e;
}
}
上面init主要處理一些初如化工作,如記錄onDragStart、onDrag、onDragEnd三個(gè)事件, handler為處理拖動(dòng)事件的那個(gè)元素,root為被拖動(dòng)的元素。
當(dāng)在handler上點(diǎn)擊后觸發(fā)Drag.start方法,Drag.start主要為記錄住鼠標(biāo)相對(duì)整個(gè)頁(yè)面的位置;給document注冊(cè)onmouseup、onmousemove事件,及觸發(fā)onDragStart事件。
Drag.drag方法也很簡(jiǎn)單,主要作用就是更新被搬移元素位置,同時(shí)記錄住鼠標(biāo)相對(duì)整個(gè)頁(yè)面的位置。
Drag.end方法就更簡(jiǎn)單了,就是做一些收尾工作。
最后給大家附段使用的代碼吧,祝大家學(xué)習(xí)愉快!
復(fù)制代碼 代碼如下:
Drag.init({
handler: document.getElementById("handler"),
root:document.getElementById("root");
});
<div id="root">
<h2 id="handler"></h2>
</div>
相關(guān)文章
JS基于正則表達(dá)式實(shí)現(xiàn)的密碼強(qiáng)度驗(yàn)證功能示例
這篇文章主要介紹了JS基于正則表達(dá)式實(shí)現(xiàn)的密碼強(qiáng)度驗(yàn)證功能,涉及javascript事件響應(yīng)及基于正則的字符遍歷、判斷等相關(guān)操作技巧,需要的朋友可以參考下2017-09-09JavaScript實(shí)現(xiàn)文字與圖片拖拽效果的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)文字與圖片拖拽效果的方法,涉及javascript操作文字與圖片的技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02js打造數(shù)組轉(zhuǎn)json函數(shù)
這里給大家分享的是一段使用js實(shí)現(xiàn)數(shù)組轉(zhuǎn)換成json的函數(shù)代碼,代碼簡(jiǎn)潔易懂,并附上了使用方法,小伙伴們拿去試試。2015-01-01JavaScript實(shí)現(xiàn)倒計(jì)時(shí)跳轉(zhuǎn)頁(yè)面功能【實(shí)用】
本文分享了JavaScript實(shí)現(xiàn)倒計(jì)時(shí)跳轉(zhuǎn)頁(yè)面功能的具體實(shí)例代碼,頁(yè)面代碼簡(jiǎn)單,直接拷貝就能運(yùn)行,頁(yè)面可以自己美化下哦。需要的朋友一起來(lái)看下吧2016-12-12JavaScript面向?qū)ο蟪绦蛟O(shè)計(jì)教程
這篇文章主要介紹了JavaScript面向?qū)ο蟪绦蛟O(shè)計(jì)教程的相關(guān)資料,需要的朋友可以參考下2016-03-03如何阻止復(fù)制剪切和粘貼事件為了表單內(nèi)容的安全
提交表單內(nèi)容如(密碼)重要信息時(shí),為了安全,需要阻止一些復(fù)制剪切和粘貼事件,下面與大家分享一個(gè)實(shí)例,感興趣的朋友可以參考下哈2013-05-05JavaScript打開word文檔的實(shí)現(xiàn)代碼(c#)
在C#中打開word文檔其實(shí)不算太難,方法也比較多,用javascript怎么打開呢?其實(shí),也不難2012-04-04js中判斷兩個(gè)數(shù)組對(duì)象是否完全相等
這篇文章主要介紹了js中判斷兩個(gè)數(shù)組對(duì)象是否完全相等方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04