html5滑鼠拖動排序及resize實現方案分析及實踐
對列表進行拖動排序,尺寸改變。之前一般會使用jQuery-UI。其通過mousedown、mousemove、mouseup這三個事件來實現頁面元素被滑鼠拖拽的效果。vue-drag-resize vuedraggable等包也大抵如此:https://codepen.io/lujun-zhou/pen/LYybXNx。
而HTML5中直接提供了拖放的API,只要通過監聽元素的拖放事件就能實現各種拖放功能。
拖放(Drag和 drop)是 HTML5 標準的組成部分。相比之前用jquery-UI等庫實現,更加方便(省去計座標計算等)。
為了使元素可拖動,必須把 draggable 屬性設定為 true:
<divid=testdraggable=true>test</div>[objectObject]
整個拖拽事件觸發的順序如下:dragstart-> drag -> dragenter -> dragover -> dragleave -> drop ->dragend
拖放事件事件詳情
一個元素被拖放,他可能會經過很多個元素上,最終到達想要放置的元素內。這裡,我暫時把被拖放的元素稱為源物件,被經過的元素稱為過程物件,到達的元素稱為目標物件。不同的物件產生不同的拖放事件。
源物件事件:
dragstart:源物件開始拖放,開始移動時事件觸發
drag:源物件拖放過程中,移動被拖拽物件時觸發
dragend:源物件拖放結束,整個拖放操作結束時觸發。
過程物件事件:
dragenter:源物件進入過程物件範圍內,被拖拽物件進入過程物件時被觸發
dragover:源物件在過程物件範圍內移動,被拖拽物件在過程物件內移動時觸發
dragleave:源物件離開過程物件的範圍,被拖拽物件離開目標物件時觸發
目標物件事件:
drop:源物件拖放到目標物件中,目標物件完全接受被拖拽物件時觸發,可理解為在目標物件內鬆手時觸發。
dragenter和dragover事件的預設行為是拒絕接受任何被拖放的元素。因此,我們必須阻止瀏覽器這種預設行為。e.preventDefault();
如果drop接收盒子要想接收到元素,那麼接收的拖動元素dragenter和dragover必須阻止預設行為。
el.ondragover=function(e){ e.preventDefault(); } el.ondrop=function(e){ e.preventDefault(); }
在vue專案中:
@dragstart.native="dragStart(index,$event)" @dragenter.native.prevent="dragenter(index,$event)" @dragleave.native.prevent @dragover.native.prevent @dragend.native="dragend(index,$event)" @drop.native.prevent="drop(index,$event)"
這樣才會觸發drop
dataTransfer物件
在所有的拖放事件中都提供了一個數據傳輸物件dataTransfer,主要是用於在源物件和目標物件之間傳遞資料。
dataTransfer方法
setData(format, data)
設定拖拽事件中要傳遞的資料,format的引數為資料型別,data要存入的資料。例如:event.dataTransfer.setData('text/plain', 'hello world')
存入的資料型別,共有4種:
-
text/plain
-
text/html
-
text/xml
-
text/uri-list
注:如果給定型別的資料不存在,則將其新增到拖動資料儲存的末尾,使得dataTransfer.types列表中的最後一個專案將是新型別。
getData(format)
該方法從dataTransfer物件中讀取資料,引數為在setData方法中指定的資料型別,例如:event.dataTransfer.getData('text/plain')
clearData()
該方法清空dataTransfer物件中儲存的資料,引數可選,為資料型別。若為空,則清空所有資料。
setDragImage(element,x,y)
-
該方法通過img元素來設定拖放圖示
-
element表示拖拽時滑鼠下面的圖片(通常是image元素,也可以說canvas元素)
-
x、y分別指示相對於圖片的橫向和縱向偏移量,相對應滑鼠指標。
dataTransfer屬性
dropEffect 和 effectAllowed屬性
給指定拖放操作所允許的一個效果,例如:dataTransfer.effectAllowed = "move"。
-
effectAllowed用來指定當元素被拖放式所允許的視覺效果。如果effectAllowed屬性是定為none,則不允許拖放元素
-
dropEffect 表示拖放操作的視覺效果,如果dropEffect 屬性設定為none,則不允許被拖放到目標元素中。
應該在dragstart事件中設定此屬性,以便為拖動源設定所需的拖動效果。在 dragenter 和dragover 事件處理程式中,該屬性將設定為在dragstart 事件期間分配的任何值,因此,可以使用effectAllowed來確定允許哪個效果。其值如下(dropEffect只有none 、copy、move、link):
none 、copy、move、link,copyMove,linkMove、all、uninitialized
chrome 預設是顯示一個綠色的加號,設定:$event.dataTransfer.effectAllowed = 'move'。則恢復成預設滑鼠樣式。
files屬性
返回被拖拽的檔案列表,是一個FileList物件,有length屬性,可通過下標訪問。此功能可用於將檔案從使用者桌面拖動到瀏覽器。一般配合FileReader來處理檔案。如FileReader.readAsDataURL與FileReader.onload
拖動元素排序實現
之前寫了兩篇文章,有讀者留言希望看程式碼,這次大致寫了下
https://codepen.io/lujun-zhou/pen/KKmNgxv
vue實現
https://codepen.io/lujun-zhou/pen/zYwozMZ
magicBox tab 排序也是,就是採用這個
畫布元素位置與尺寸調整
可以先回顧下《再談BOM和DOM(6):dom物件及event物件位值計算—如offsetX/Top,clentX》
如果使用mouse事件控制,就顯得非常複雜。這種一般都是使用第三方庫實現,如interact.js 、vue-drag-resize等。
如果直接使用 css resize,然後通過 resizeObserve 回撥尺寸改變,實現起來就變得簡單的多。
這種思路之前也介紹過,如《懶載入優化:JavaScript IntersectionObserver API監聽元素是否可見》。
這裡的大致實現程式碼:
https://codepen.io/lujun-zhou/pen/jOmVLGy
之前做過一版類似DataV的需求,就是直接用html5 原生屬性寫的。
canvas 畫布實現:https://codepen.io/atindo23/pen/OJLbdrJ
滑鼠縮放元素操作
縮放事件,實現不肖多說,MDN案列寫的夠好了
https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onwheel
參考文章:
HTML5--拖放事件與dataTransfer物件https://blog.csdn.net/hjc256/article/details/89021483
說說 HTML 中的dropEffect 和 effectAllowedhttps://blog.csdn.net/gggg5643/article/details/52135824
HTML5 進階系列:拖放 API 實現拖放排序 - 林鑫的文章 - 知乎https://zhuanlan.zhihu.com/p/26666141
HTML5前端技術教程:H5拖放 - 方偉景的文章 - 知乎https://zhuanlan.zhihu.com/p/47458212
轉載本站文章《html5滑鼠拖動排序及resize實現方案分析及實踐》,
請註明出處:https://www.zhoulujun.cn/html/webfront/SGML/html5/2016_0124_434.html