摘要:原生實(shí)現(xiàn)對(duì)元素的拖拽一背景介紹此處為鋪墊內(nèi)容,可跳過隨著前端的不斷發(fā)展,各種各樣的前端規(guī)范和新知識(shí)新技術(shù)層出不窮,極大地拓展了開發(fā)者的操作空間,也大大地提升了用戶體驗(yàn)。
原生 JS 實(shí)現(xiàn)對(duì) html 元素的拖拽 一、背景介紹
【此處為鋪墊內(nèi)容,可跳過】 隨著 Web 前端的不斷發(fā)展,各種各樣的前端規(guī)范和新知識(shí)、新技術(shù)層出不窮,極大地拓展了開發(fā)者的操作空間,也大大地提升了用戶體驗(yàn)。而隨著移動(dòng)端的不斷發(fā)展,在移動(dòng)端,人機(jī)交互方式發(fā)生了很大轉(zhuǎn)變,新的人機(jī)交互方式對(duì)提供給用戶的 “動(dòng)作” 有了更高要求,例如拖拽功能,就是在移動(dòng)端會(huì)經(jīng)常接觸到的功能。此文就詳細(xì)地講解一下,一個(gè)簡單的拖拽功能的實(shí)現(xiàn)(拖拽元素可改變,瀏覽器窗口邊界檢測)。
二、知識(shí)準(zhǔn)備為了讓各位對(duì)此文內(nèi)容有更深刻的掌握,需要掌握如下知識(shí)。
1、clientX,clientY 屬性
clientX( clientY ) 事件屬性返回當(dāng)事件被觸發(fā)時(shí)鼠標(biāo)指針相對(duì)于瀏覽器當(dāng)前可視窗口的水平(垂直)坐標(biāo)。
注意:不包括工具欄和滾動(dòng)條
2、offsetTop,offsetLeft 屬性
offsetTop ( offsetLeft ),指的是子元素距離其父元素的上邊框(左邊框)的偏移量,在不同的瀏覽器中其值不同,且與父元素的 position 屬性( position: static; 除外)有關(guān)。在不同瀏覽以及不同 position 下的具體值,讀者可以自行查閱相關(guān)資料,因其內(nèi)容較多,就不展開論述了。
3、clientWidth,clientHeight屬性
Element.clientWidth( Element.clientHeight )屬性表示元素的內(nèi)部寬度,以像素計(jì)。該屬性包括內(nèi)邊距,但不包括垂直滾動(dòng)條(如果有)、邊框和外邊距。該屬性值會(huì)被四舍五入為一個(gè)整數(shù)。如果你需要一個(gè)小數(shù)值,可使用 element.getBoundingClientRect() 。
4、setCapture,releaseCapture 方法
三、實(shí)現(xiàn)思路MDN 對(duì) SetCapture() 函數(shù)的說明為:“該函數(shù)在屬于當(dāng)前線程的指定窗口里設(shè)置鼠標(biāo)捕獲。一旦窗口捕獲了 鼠標(biāo),所有鼠標(biāo)輸入都針對(duì)該窗口,無論光標(biāo)是否在窗口的邊界內(nèi)。同一時(shí)刻只能有一個(gè)窗口捕獲鼠標(biāo)。如果鼠標(biāo)光標(biāo)在另一個(gè)線程創(chuàng)建的窗口上,只有當(dāng)鼠標(biāo)鍵按下時(shí)系統(tǒng)才將鼠標(biāo)輸入指向指定的窗口。”
通俗來講,舉個(gè)栗子:一只羊被一根有彈性的繩子( SetCapture )拴在木樁,羊可以在繩子可以延展的范圍內(nèi) 隨意活動(dòng),但永遠(yuǎn)無法擺脫繩子的束縛。除非有其他因素導(dǎo)致繩子斷了(使用了 ReleaseCapture 或點(diǎn)擊了其他窗口)。
ReleaseCapture() 用來釋放鼠標(biāo)捕獲,當(dāng)不再需要繼續(xù)獲得鼠標(biāo)消息就要應(yīng)該調(diào)用 ReleaseCapture() 釋放掉,否則別的線程想捕獲鼠標(biāo)事件就會(huì)失敗。注意:SetCapture() 和 ReleaseCapture() 必須成對(duì)出現(xiàn)。
如果想對(duì)元素進(jìn)行拖拽,那么必須使用三個(gè)事件,并且這三個(gè)事件的使用順序不能打亂。
1、onmousedown:鼠標(biāo)按下事件 2、onmousemove:鼠標(biāo)移動(dòng)事件 3、onmouseup:鼠標(biāo)抬起事件
拖拽的基本原理就是根據(jù)鼠標(biāo)的移動(dòng)來移動(dòng)被拖拽的元素。鼠標(biāo)的移動(dòng)也就是 x、y 坐標(biāo)的變化;元素的移動(dòng)就是元素 position 屬性的 top 和 left 值的改變。當(dāng)然,并不是任何時(shí)候移動(dòng)鼠標(biāo)都要造成元素的移動(dòng),而應(yīng)該判斷鼠標(biāo)左鍵的狀態(tài)是否為按下狀態(tài),是否是在可拖拽的元素上按下的。具體過程如下:
拖拽狀態(tài)?=?false 鼠標(biāo)在元素上按下之后 { 拖拽狀態(tài)?=?true 設(shè)置鼠標(biāo)捕獲 記錄下鼠標(biāo)的 x,y 坐標(biāo) 記錄下元素的 x,y 坐標(biāo) } 鼠標(biāo)在元素上移動(dòng)時(shí) { 若拖拽狀態(tài)為 false 就什么也不做 如果拖拽狀態(tài)是 true,那么 元素的 y?坐標(biāo) =?現(xiàn)在鼠標(biāo) y?-?原來鼠標(biāo) y?+?原來元素 y 元素的 x?坐標(biāo) =?現(xiàn)在鼠標(biāo) x?-?原來鼠標(biāo) x?+?原來元素 x } 鼠標(biāo)抬起時(shí) { 拖拽狀態(tài)?=?false }四、完整源碼
原生JS實(shí)現(xiàn)元素拖拽
五、案例總結(jié)注意事項(xiàng)
1、onmousedown 事件中的操作對(duì)象為拖拽元素,而 onmousemove 和 onmouseup 事件中的操作對(duì)象為 document,這是因?yàn)椋c(diǎn)擊某物體時(shí),用需要拖拽的對(duì)象即可,onmousemove 和 onmouseup 是全局區(qū)域,也就是整個(gè)文檔通用,應(yīng)該使用 document 對(duì)象而不是被拖拽的對(duì)象(否則,采用拖拽對(duì)象時(shí)物體只能往右方或下方移動(dòng))2、之所以使用 setCapture() 和 releaseCapture(),其目的是為了修復(fù)低版本 IE 的 bug。在低版本 IE 下,當(dāng)我們在要拖動(dòng)的元素上,按下鼠標(biāo)按鈕拖動(dòng)時(shí),當(dāng)拖動(dòng)過快,或者是超出瀏覽器的文檔窗口時(shí),拖動(dòng)對(duì)象身上的 onmousedown 事件就會(huì)失效。在 Chrome 我們可以為 doucment 綁定 onmouseout 事件來判斷是否發(fā)生這樣的情況,但是 IE 下卻行不通,所以最好的解決辦法就時(shí)為要拖動(dòng)的元素對(duì)象鎖定鼠標(biāo)事件,在拖動(dòng)后再解除事件鎖定。在本例中,這兩個(gè)方法用于 onmousedown 和 onmouseup 中。
3、另外,在 Firefox 中有相似的功能,它們分別是:
captureEvents ( Event.eventType )
releaseEvents ( Event.eventType )
雖然元素的拖拽算是一個(gè)比較基礎(chǔ)的知識(shí)點(diǎn),但在實(shí)現(xiàn)的過程中,有許多細(xì)節(jié)需要注意,例如計(jì)算坐標(biāo)的時(shí)候,對(duì)那幾個(gè)屬性的了解程度,再例如,事件的觸發(fā)順序,還有,IE 中的事件獲取, setCapture() 和 releaseCapture() 等。
雖然 H5 直接提供了拖拽 API,但為了兼容性,小伙伴們還是需要用 js 去處理的。上例中,雖然對(duì)拖拽做了一定的兼容性處理和封裝,拖拽對(duì)象可以是 div,圖片,文字等,但總的來說,是一個(gè)比較基礎(chǔ)的實(shí)現(xiàn),但有了這個(gè)原型,小伙伴們可以根據(jù)自己的需求,再加以封裝和拓展,例如限定拖拽方向、范圍、速度等等。有任何疑問或建議,可以在評(píng)論區(qū)留言哦,轉(zhuǎn)載請(qǐng)注明出處。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/105116.html
摘要:原生實(shí)現(xiàn)對(duì)元素的拖拽一背景介紹此處為鋪墊內(nèi)容,可跳過隨著前端的不斷發(fā)展,各種各樣的前端規(guī)范和新知識(shí)新技術(shù)層出不窮,極大地拓展了開發(fā)者的操作空間,也大大地提升了用戶體驗(yàn)。 原生 JS 實(shí)現(xiàn)對(duì) html 元素的拖拽 一、背景介紹 【此處為鋪墊內(nèi)容,可跳過】 隨著 Web 前端的不斷發(fā)展,各種各樣的前端規(guī)范和新知識(shí)、新技術(shù)層出不窮,極大地拓展了開發(fā)者的操作空間,也大大地提升了用戶體驗(yàn)。而隨著...
摘要:前面幾篇文章,我跟大家分享了的一些基礎(chǔ)知識(shí),這篇文章,將會(huì)進(jìn)入第一個(gè)實(shí)戰(zhàn)環(huán)節(jié)利用前面幾章的所涉及到的知識(shí),封裝一個(gè)拖拽對(duì)象。不封裝對(duì)象直接實(shí)現(xiàn)利用原生封裝拖拽對(duì)象通過擴(kuò)展來實(shí)現(xiàn)拖拽對(duì)象。 showImg(https://segmentfault.com/img/remote/1460000008699587); 前面幾篇文章,我跟大家分享了JavaScript的一些基礎(chǔ)知識(shí),這篇文章,...
摘要:涉及部分的,不會(huì)對(duì)理解全局產(chǎn)生干擾。在上監(jiān)聽事件,當(dāng)為畫布時(shí),通過創(chuàng)建一個(gè)藍(lán)色虛線框移動(dòng)的時(shí)候,更新的位置在上監(jiān)聽事件,落在畫布時(shí),創(chuàng)建一個(gè)的節(jié)點(diǎn)從而完成整個(gè)拖拽添加元素的功能。 showImg(https://segmentfault.com/img/remote/1460000019564977);showImg(https://segmentfault.com/img/remot...
摘要:涉及部分的,不會(huì)對(duì)理解全局產(chǎn)生干擾。在上監(jiān)聽事件,當(dāng)為畫布時(shí),通過創(chuàng)建一個(gè)藍(lán)色虛線框移動(dòng)的時(shí)候,更新的位置在上監(jiān)聽事件,落在畫布時(shí),創(chuàng)建一個(gè)的節(jié)點(diǎn)從而完成整個(gè)拖拽添加元素的功能。 showImg(https://segmentfault.com/img/remote/1460000019564977);showImg(https://segmentfault.com/img/remot...
閱讀 3451·2023-04-25 19:39
閱讀 3799·2021-11-18 13:12
閱讀 3634·2021-09-22 15:45
閱讀 2433·2021-09-22 15:32
閱讀 716·2021-09-04 16:40
閱讀 3726·2019-08-30 14:11
閱讀 1883·2019-08-30 13:46
閱讀 1563·2019-08-29 15:43