圖形編輯器中JS實現防誤操作之拖拽阻塞
圖形編輯器中
在圖形編輯器中,想象這麼一個場景,我們撤銷瞭一些重要的操作,然後想選中一個圖形,看看它的屬性。你點瞭上去,然後你發現你再也無法重做瞭。
你以為你點瞭一下,但其實你點擊的時候,鼠標還是小小移動瞭一點,飄瞭一個像素點。對編輯器來說,它識別到讓圖形移動一個像素點的操作,就生成瞭一個新的版本,然後重做棧(redoStack)被清空瞭,你退回前的操作就沒瞭。
為瞭解決這類用戶微小操作的問題,我們可以巧妙地給拖拽行為加一個 阻塞閾值。具體就是就是按下鼠標後,移動鼠標的距離要大於某個值,我們才認為發生瞭拖拽,並執行對應工具的邏輯。
下面為我們要實現的效果。此處為瞭更好地演示效果,將閾值設置得很大。通常設置個 4px 就夠瞭。
可以看到,按下鼠標然後移動,如果移動的位移太小,矩形是不會被移動的,直到達到一定位移閾值後,矩形才會乖乖聽話跟隨鼠標進行移動。
閾值表示位移距離,使用的是視口坐標系,而不是場景坐標系。
代碼改造
原來的邏輯:
let isPressing = false; let currentTool = null; // 當前工具對象 // 鼠標按下 function handleDown(e) { isPressing = true; currentTool.start(e); } // 鼠標移動 function handleMove(e) { if (isPressing) { currentTool.drag(e); } else { // 非拖拽的移動事件 // 比如選擇工具停留在圖形上,圖形要高亮,此時沒發生拖拽 currentTool.move(e); } } // 鼠標釋放 function handleUp(e) { currentTool.end(e); isPressing = false; }
鼠標按下時,isPressing 設置為 true,表示發生瞭鼠標按下事件。
此時鼠標再移動,我們就能知道這是一個 “拖拽” 的行為,即按下鼠標不放然後移動鼠標的行為。此時調用工具對象的 drag 方法。
最後鼠標釋放,將狀態 isPressing 重置。
現在我們進行改造。
let isPressing = false; let currentTool = null; // 當前工具對象 let isEnableDragging = false; // 是否調用工具對象的 drag 方法 let startPos = null; // 保存鼠標按下時的坐標 const blockStep = 4; // 閾值 function handleDown(e) { isPressing = true; isEnableDragging = false; startPos = { x: e.clientX, y: e.clientY }; currentTool.start(e); } function handleMove(e) { // 判斷位移是否突破閾值,是的話更新狀態為 “可拖拽” if ( !isEnableDragging && (Math.abs(e.clientX - startPos.x) > blockStep || Math.abs(e.clientX - startPos.x) > blockStep) ) { isEnableDragging = true; } if (isPressing) { if (isEnableDragging) { // “可拖拽” 狀態,調用工具的 drag 方法 currentTool.drag(e); } } else { currentTool.move(e); } } function handleUp(e) { currentTool.end(e); // 初始化狀態 isPressing = false; isEnableDragging = false; startPos = null; }
核心思路是引入 isEnableDragging 狀態,表示鼠標移動時,是否達到移動的條件。
我們在鼠標移動事件中,計算鼠標按下和鼠標移動之間的距離是否超過某個值,如果超過閾值,就將 isEnableDragging 狀態轉換為 true。
然後判斷 isEnableDragging 為 true,就調用工具對象的 drag 方法。
需要註意的是,不要隻用位移距離來判斷是否可以拖拽,要配合狀態。否則突破閾值後,又移動回來,你會發現你又卡住瞭,因為此時閾值因為再次計算,沒能達到閾值。
所以加瞭個 isEnableDragging 狀態,在第一次突破閾值設置為 true 後,就再也不用計算位移瞭,之後一直都是可拖拽狀態,直到鼠標釋放重置狀態。
結尾
拖拽阻塞是開發圖形編輯器的一點小細節,並不復雜,但能帶來很好的用戶體驗。
以上就是圖形編輯器中JS實現防誤操作之拖拽阻塞的詳細內容,更多關於JS 拖拽阻塞的資料請關註WalkonNet其它相關文章!