移動端h5實現(xiàn)拖拽的兩種方法(移動端h5實現(xiàn)拖拽的兩種方法是)
移動端的項目經(jīng)常會引入手勢庫來實現(xiàn)拖拽
不過如果只是一兩個頁面用到拖拽,再引入一個手勢庫就很不劃算
最近的項目中就有這么一個需求:
需求
因為就這一個地方需要拖拽,所以我就沒有引入第三方庫
移動端的拖拽有兩種主流的實現(xiàn)方案:
1. 將元素設(shè)置為固定定位,然后在拖拽的時候修改其定位,實現(xiàn)拖拽的效果;
2. 使用 transform 中的平移 translate 屬性實現(xiàn)拖拽。
方案一:固定定位 fixed
這種方案的核心就是給元素添加固定定位 position:fixed;
但定位之后,元素會脫離文檔流,會影響原有但布局
因此在開始拖拽 (觸發(fā) touchstart 事件) 的時候,需要將原本的元素 A 拷貝一份 ( cloneNode() )
給新元素 A2 添加定位,同時給原本的元素 A 設(shè)置 visibility: hidden; 使之隱藏并占位
1.1 創(chuàng)建遮罩
首先封裝一個創(chuàng)建遮罩的方法,用于放置拷貝出來的元素,并防止誤觸
創(chuàng)建遮罩
1.2 開始拖拽
在觸發(fā) touchstart 事件的時候,首先創(chuàng)建遮罩
并通過 getBoundingClientRect() 方法獲取到元素 A 的坐標,記錄起點信息
為了記錄起點信息,需要 data 中創(chuàng)建一個對象 source,用于記錄點擊的位置 client,和初始定位坐標 start
開始拖拽
1.3 處理拖拽
拖拽的時候,監(jiān)聽 touchmove 事件
用【當前鼠標點位置】減去【初始點擊位置】得到移動的距離
再結(jié)合初始坐標信息,更新拖拽元素的坐標
處理拖拽
1.4 拖拽結(jié)束
拖拽結(jié)束的時候,記錄終點位置,刪除遮罩
拖拽結(jié)束
不過上面的代碼只實現(xiàn)了拖拽的功能,并沒有對目標元素 A 進行顯示/隱藏的操作
可以根據(jù)業(yè)務(wù)場景自行添加,或者參考方案二
方案二:平移動畫 translate
這種方案更為簡單,不需要創(chuàng)建額外的 DOM 元素
只需對原本的元素添加 transform 屬性,甚至不需要 transition 屬性
然后在拖拽過程中,實時更新 transform: translate(X, Y) 中 x, y 的坐標信息,實現(xiàn)拖拽
2.1 開始拖拽
開始拖拽的時候,只需要記錄起點坐標
開始拖拽
為了防止拖拽的過程中誤觸,建議使用方案一的 createModal() 方法創(chuàng)建一個遮罩
2.2 處理拖拽
根據(jù)當前坐標和起點坐標,計算出距離,然后更新 translate 的坐標
處理拖拽
2.3 拖拽結(jié)束
拖拽完成后,清除平移動畫
拖拽結(jié)束
小結(jié):
方案一在獲取目標元素的坐標信息的時候使用了 getBoundingClientRect() 方法
但這個方法性能不高,應(yīng)當少用
而且即時使用了該方法,最后得到的 left 和 top 也不夠精確,touchstart 的時候,元素有明顯的閃動
我的項目使用了 vue.js,但拖拽功能用到 vue 的地方不多,將幾個用于記錄的對象提出來,就能復用于其他框架