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