從GGEditor的一個案例看JS原生拖拽功能

ReactG6JSGGEditor

拖拽操做平時用的比較少,在最近的一個項目中使用到了,而且踩了一些坑,本文作一個簡單的總結。涉及部分G6的API,不會對理解全局產生干擾。

需求概述

以下圖所示,左側爲GGEditor元素面板React組件,右側爲G6畫布,現須要將元素從「元素面板」中拖拽到「畫布」上。要求:html

  • 拖拽時藍色虛線框和元素面板的對應元素尺寸相同(爲一矩形)
  • 藍色虛線框跟隨鼠標移動,指明當前拖拽的位置
  • 元素面板上對應元素不該發生改變

    圖片描述

⚠️圖中的黑色圓圈僅爲錄屏軟件指明鼠標操做提示html5

拖拽方法總結

相較於大部分DOM操做只須要監聽某一種事件,原生拖拽功能的實現一般須要監聽所有或部分的下述事件:react

事件 event.target 觸發時機
drag 被拖動元素 拖拽中(每幾百毫秒觸發一次)
dragstart 被拖動元素 剛開始拖拽
dragend 被拖動元素 拖拽結束(鼠標釋放或esc
dragover 被拖動元素下方元素 拖拽到某一目標上時(每幾百毫秒一次)
dragenter 被拖動元素下方元素 被拖動元素進入可釋放處時
dragleave 被拖動元素下方元素 拖拽離開某一目標時
drop 被拖動元素下方元素 dragend 且在其以前觸發

需求實現

實現以前,有幾個踩坑點先說明:canvas

  • 不能將左側面板的元素設置爲draggable,由於原生拖拽自帶陰影效果,以下圖。

圖片描述
很明顯這不是咱們要的效果。api

  • 拖拽時的藍色虛線框應該由G6繪製成一個canvas的元素,由於畫布能夠放大或縮小,這個虛線框應和實際放在畫布上的元素尺寸相同而不是左側面板的元素尺寸相同。(不瞭解G6的同窗自行忽略

思路

  1. 拖拽開始或鼠標落下時,建立一個和元素大小寬高相同的透明度爲0的矩形shadowShape,並監聽其dragmouseup事件。
  2. document上監聽dragenter事件,當target爲畫布時,經過G6api建立一個藍色虛線框dragShape
  3. shadowShape移動的時候,更新dragShape的位置
  4. document上監聽drop事件,落在畫布時,建立一個G6的節點從而完成整個拖拽添加元素的功能。
  5. ⚠️踩坑點:必需要阻止dragover的默認行爲,保證drop的正常觸發,參考這則問答

圖片描述

總結

1 相較於上個版本的GGEditor,實現了拖拽功能的連續性。以前,鼠標即便保持按下,一旦移出畫布,就終止了本次的拖拽過程。less

圖片描述
上個版本的GGEditor優化

2 待優化點:spa

  • 因爲藍色虛線框是G6畫布上的元素,可以根據G6的縮放比例自動調整大小,因此在其餘地方的拖拽過程不易作出相似的虛線框,體驗上有間斷感
  • 當前代碼在一個react組件裏操做了大量的原生事件監聽,不夠React,考慮以後直接開發一個新的組件,使用React的合成事件來重寫。
相關文章
相關標籤/搜索