摘要:前言魯迅說過如果你的技術不好,那么你的姿勢要多。元素不是被拖動目標時。先實現拖動的效果,大概就是這樣在的時候記下必要的信息將小強的改成在記錄下鼠標在軸上移動的距離,橫行的話就是這樣基本的拖動問題是解決了,元素最起碼是可以拖動起來了。
前言
魯迅說過:“如果你的技術不好,那么你的姿勢要多。”
公司的項目最近給側邊欄加了拖動排序的效果,類似于下面這種效果(魯迅:不是我的下面),是下面的圖?:
說來慚愧,上圖不是我寫的,不然我還能吹一波,沒有看代碼,但閉著眼就能猜到用的是html5的drag系列的api,相關的API可以看MDN上的介紹,我把文檔拷一下做個介紹吧==
drag: 當元素或者選擇的文本被拖動時觸發drag事件 (每幾百毫秒)。
dragstart: 當用戶開始拖動一個元素或者一個選擇文本的時候dragstart事件就會觸發。一般在這個動作里面處理被拖動元素的樣式。
dragend: 拖動操作結束時觸發,即松開鼠標操作。
dragenter: a拖到b中的時候觸發。
dragover: 拖動過程不斷觸發。
dragexit: 元素不是被拖動目標時。
dragleave: a拖到b,不釋放鼠標,再拖到c,離開b的時候觸發。
drop: 當一個元素或是選中的文字被拖拽釋放到一個有效的釋放目標位置時
上面的大部分都是對樣式之類的處理,官方也給了例子,排除掉drag和dragover這兩個觸發大戶,大概的順序是這樣的:
首先,我肯定是實現了效果的,如下圖所示的:
粗略介紹下流程吧,首先需要確定的是應該是什么效果,打個比方,我把a拖到了b上,b能很明顯的感覺到,“啊,有什么奇怪的東西進入我的體內了”。但是b并不知道a是想在前面還是想在后面...這時候你就發現問題了吧,對!提問:“a和b到底誰在上面誰在下面?”所以我們剛開始要約定一個規范,把上面的a拖向下面的b,那么就把a排在b的下面,反之,把下面的a拖向上面的b,那么就把a放在b的上面~首先我需要這四個對象:
let dragObj, enterObj, dragIndex, enterIndex; // dragObj 被拖動的對象a,整個拖動過程它是不會變的 // enterObj 最終進入的對象b,在drop里可以獲取到 // dragIndex a在列表中的下標 // enterIndex b在列表的下標
通過比較dragIndex和enterIndex的大小來決定a和b的關系,剩下的就是對dom進行操作了:
if (dragIndex < enterIndex) { dragObj.remove(); enterObj.after(dragObj); } else if (dragIndex > enterIndex) { dragObj.remove(); enterObj.before(dragObj); }???
是不是相當簡單了效果預覽 (chrome下觀看)
源碼
直接看看效果吧,也可以做個比較:
預覽效果
使用到的api:onmousedown, onmousemove, onmouseup,其實這些大家多多少少應該會用過,但我還是在這里粗略介紹下:
onmousedown: 在當前元素上點擊鼠標按鍵時會觸發mousedown事件,有人問了,那這個和click有什么區別呢,區別是 click = mousedown + mouseup,然后是,click鼠標左鍵觸發,mousedown鼠標點擊即會觸發。
onmousemove: 當用戶在當前元素上移動鼠標時會觸發mousemove事件,就是“拖動元素。
onmouseup: 當用戶在當前元素上放開鼠標某個按鍵時會觸發mouseup事件。
整個實現過程也比上面的那一種要復雜的多,不同與drag,drag自己能感知元素從a移動到了b中或者從b中離開,而鼠標事件不行。
拖動注意點這樣一個列表:
假設我點了“小強”,“小強”被我選中,我怎么去實現拖動的效果呢?元素本身是沒有拖動這個說法的,我能做到的就是動態的改變它的位置,那就是在onmousemove的時候動態的去改變了,改變元素位置且不影響到其他元素排布的,那就是absolute了。先實現拖動的效果,大概就是這樣:
//在onmousedown的時候記下必要的信息,將小強的position改成absolute const startY = event.clientY; //在onmousemove記錄下鼠標在y軸上移動的距離,橫行的話就是x const currentTop = parseInt(startTop) + (moveY - startY);
這樣基本的拖動問題是解決了,元素最起碼是可以拖動起來了。這里需要注意的是,只有“小強”的位置是absolute,這時候“小明”就會被小強遮住,所以我們這里需要一個元素“占位”:
--“進來了嗎?” --“不是早就進來了”各位乘客系好安全帶,我要開車了...
理想的效果應該是這樣的,“小強”向下拖動,距離“小明”底部小于一半時,“小明”就應該給“小強”讓路,“小明”要知道小強什么時候進來了,然后hold元素向下移動一格,說明小強“此時”已經在“小明”下面了:currentTop > itemHeight + itemHeight / 2;記錄高度實在是沒必要,我只需要記錄“小強” 當前 被拖動到“第幾位”就可以了:
currentIndex = Math.ceil((currentTop - itemHeight / 2) / itemHeight);只要拿到onmousedown時的“小強”的“index”,與當前的比較,只要兩者不相同,就需要移動hold的位置,hold元素的位置受當前index的影響:
if (previousIndex !== currentIndex) { //... }此處省略的代碼都是dom的操作,不做太多說明。此時我們并沒有對拖動的元素做限制,元素能夠被拖到盒子的外面,這樣肯定是不可以的,做一個限制:
if (currentIndex < 0) { currentIndex = 0; } else if (currentIndex > listLength - 1) { currentIndex = listLength - 1; }這樣不會限制的用戶拖動的操作,我們只需要控制住index就好了,這樣處理也方便的多。
在用戶onmouseup的時候需要對監聽器進行銷毀:document.onmousemove = null; document.onmouseup = null;注意事項類似于$$和querySelectorAll獲取到的"數組"并不是“數組”,它有數組的部分特性,通過下圖我們可以知道它是一個NodeList,并不是Array,它是有forEach方法的,但是它并沒有map、find等一系列方法,使用的時候還需注意。
源碼細節還是看源碼吧 我在剛開始寫的時候碰到很多坑,dom操作的時候更是,尤其在上下來回拖動的時候,具體的不再多講,因為實在有點晚了。對不起,我今晚玩游戲玩到十一點半,我有罪==,洗個澡啥的,弄的很晚。
享受coding,熱愛生活,拜~文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/112828.html
相關文章
用兩種不同的姿勢來實現拖動排序
摘要:前言魯迅說過如果你的技術不好,那么你的姿勢要多。元素不是被拖動目標時。先實現拖動的效果,大概就是這樣在的時候記下必要的信息將小強的改成在記錄下鼠標在軸上移動的距離,橫行的話就是這樣基本的拖動問題是解決了,元素最起碼是可以拖動起來了。 前言 魯迅說過:如果你的技術不好,那么你的姿勢要多。 showImg(https://segmentfault.com/img/bVZSnT?w=500&...
可拖動table表頭的實現
摘要:前言自己做的項目碰到這樣一個需求,就是對所有的表格添加表頭可以拖動的效果。需要說明的是,表頭固定的那種是需要用兩個去實現,做過的人應該也都明白。拜拜后續補充更改了寬度改變的方式,應該是只改變拖動列后面的列的寬度。 前言 自己做的項目碰到這樣一個需求,就是對所有的表格添加表頭可以拖動的效果。我一想,這不簡單,分分鐘鐘給你做出來。拿起我的電腦,啪啪啪就敲起來了。showImg(https:...
可拖動table表頭的實現
摘要:前言自己做的項目碰到這樣一個需求,就是對所有的表格添加表頭可以拖動的效果。需要說明的是,表頭固定的那種是需要用兩個去實現,做過的人應該也都明白。拜拜后續補充更改了寬度改變的方式,應該是只改變拖動列后面的列的寬度。 前言 自己做的項目碰到這樣一個需求,就是對所有的表格添加表頭可以拖動的效果。我一想,這不簡單,分分鐘鐘給你做出來。拿起我的電腦,啪啪啪就敲起來了。showImg(https:...
發表評論
0條評論
閱讀 3284·2021-11-24 09:39
閱讀 3865·2021-11-22 09:34
閱讀 4799·2021-08-11 11:17
閱讀 1060·2019-08-29 13:58
閱讀 2570·2019-08-28 18:18
閱讀 537·2019-08-26 12:24
閱讀 825·2019-08-26 12:14
閱讀 726·2019-08-26 11:58