原生js實現九宮格拖拽換位
阿新 • • 發佈:2021-01-28
使用原生JS寫出一個九宮格,實現九個格子何以拖拽換位的效果,供大家參考,具體內容如下
效果演示
具體思路分析和程式碼:
圖解1:
程式碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>Document</title> <!-- 思路梳理: 1,樣式設定:在樣式裡最好使用定位來佈局,不然以後拖拽程式碼會麻煩點兒。 (這裡沒有設定父容器的具體位置,如果設定了父容器的具體位置,則在移動 時top和left的值需要根據情況計算位置) 2,父容器盒子裡的內容最好使用js程式碼來生成,方便使用和新增樣式 2-1:(迴圈生成子元素) 我們子元素使用的定位佈局,不難發現:每行的top值一樣,每列的left值一樣,因此迴圈生 成子元素我們可以使用3*3的迴圈巢狀來寫,這樣就可以講每行的樣式設定了。 2-2:(給迴圈生成的標籤新增隨機顏色和文字) 隨機顏色我是用的時rgb()來實現的,文字可以使用ASCII碼來生成,也可以使用字串拼接 來生成,我這裡使用ASCII碼生成。 PS:這樣我們的基本樣式就設定完畢了,接下來就是設定拖拽的事件 3,給每一個元素新增事件,這裡我們需要三個事件: onmousedown - onmousemove - onmouseup 3-1:(首先是按下事件 onmousedown) 當我們在對應子元素按下時,我們要獲取滑鼠到按下目標邊框線內的距離,並且克隆這個元素, 將這個元素扔到父容器裡面充當佔位,(這裡注意,克隆的這個節點在HTML結構裡是放到最後 的,如果不處理後面會出BUG!!!)。 3-2:(然後處理移動事件 onmousemove) 在按下子元素塊兒並且移動時,我們要給目標設定他的top和left值,來實現跟隨移動,所以 我們需要獲取滑鼠到可視視窗的距離,目標的top和left值 = 滑鼠到可視視窗的距離 - 滑鼠 到目標邊緣的距離(這裡無邊框,如果有需要額外減去邊框寬度)。 PS: 這裡存在一個BUG!!!!在拖拽時,存在一個預設事件--選中文字,當你鬆開之後,目 標還會跟著走,就算你關閉了onmousemove這個事件。所以這裡需要阻止一下預設事件。 3-3:(最後處理抬起事件 onmouseup)這裡也是最重要的一步!!!! 核心思想: 當滑鼠抬起時,我們要計算當前移動目標的中心點和每一個子元素中心點的距離, 哪一個離得最近,和哪個交換位置(注意,這裡存在一個BUG,這裡的BUG就是 3-1 裡提到的BUG,需要提前處理)。 具體過程: 3-3-1: 首先我們要進行迴圈,計算拖拽目標的中心點與每一個子元素的中心點的距離,具體 參照 圖解1 。 (拖拽目標距離可視視窗的左邊距 - 子元素距離可視視窗的左邊 距)平方 + (拖拽目標距離可視視窗的上邊距 - 子元素距離可視視窗的上邊距) 平方。最後在開方,得到中心點的距離(注意3-1的BUG要處理掉,把,要把移動的 標籤放到結構的最後,然後迴圈的時候將他排除掉,不然每次距離最近的都是它本身)。 3-3-2: 我們迴圈會得到我們想要的每一個距離,然後將這些距離放到一個數組裡,並且再定 義一個數組備份一下,方便對照具體是哪個標籤。 將其中一個數組進行排序,然後再備份陣列中查一下最小的值在備份陣列中的索引下 標,這個索引下標也就是對應的子元素了。 3-3-3: 然後將距離最近的子元素的 left和top值給 目標元素 然後將克隆的標籤的 left和top值給 距離最近的子元素 最後在將克隆的標籤移除掉 這裡還是會有一個BUG!!!如果不在標籤上按 直接抬起滑鼠的話,會報錯,這是因 為直接執行了onmouseup事件,所以需要移除掉onmouseup事件 --> <style> *{margin: 0;padding: 0;} .father{position: relative;} .father div{position: absolute;width: 100px;height: 100px;border-radius: 10px;text-align: center;line-height: 100px;font-size: 30px;cursor: pointer;} </style> </head> <body> <div class="father"></div> <script> // 3*3 迴圈生成子元素div,並給他們設定定位值 // 設定固定的margin值 var mT = 15; var mL = 15; var asc = 65;//ASCII碼值 var oFather = document.querySelector('.father'); for(var i = 0; i < 3; i++){ for(var j = 0; j < 3; j++){ var oDiv = document.createElement('div');//建立子元素 oFather.appendChild(oDiv); oDiv.style.left = j * (oDiv.offsetWidth + mL) +'px'; oDiv.style.top = i * (oDiv.offsetHeight + mT) +'px'; // 隨機顏色設定 oDiv.style.background = 'rgb('+parseInt(Math.random()*256) + "," +parseInt(Math.random()*256) + ","+parseInt(Math.random()*256)+')'; // 加上字母 oDiv.innerText = String.fromCharCode(asc++); } } // 為了方便理解,將事件寫到了外面,這裡可以生成標籤迴圈內部 /* var oItem = document.querySelectorAll('.father>div'); 這種方式獲取的是靜態集合,只會獲取到初次頁面載入的內容,用這種辦法獲取子元素會出BUG */ var oItem = oFather.children; for(var k = 0 ;k<oItem.length; k++){ oItem[k].onmousedown = function(e){ var evt = e || event; // 獲取滑鼠到目標邊框內的距離 var x = e.offsetX; var y = e.offsetY; var tagNode = this; // 克隆目標標籤 var cloneNode = tagNode.cloneNode(); cloneNode.style.border = '1px dashed #fff'; oFather.appendChild(cloneNode); tagNode.style.zIndex = 1; // 在思路里提到過,這裡存在一個BUG需要將克隆的和被拖拽換位置 oFather.replaceChild(cloneNode,tagNode); oFather.appendChild(tagNode); document.onmousemove = function(e){ var evt = e || event ; var l = evt.clientX - x; var t = evt.clientY - y; tagNode.style.left = l + 'px'; tagNode.style.top = t + 'px'; // 阻止預設事件,防止bug return false; } document.onmouseup = function(){ // 抬起滑鼠後,要判斷離那個最近,然後交換 var oldArr = []; var newArr = []; for(var l = 0; l<oItem.length - 1;l++){ var disX = tagNode.offsetLeft - oItem[l].offsetLeft; var disY = tagNode.offsetTop - oItem[l].offsetTop; // 勾股定理 var dis = Math.sqrt( Math.pow(disX,2) + Math.pow(disY,2) ); oldArr.push(dis); newArr.push(dis); } // 將oldArr從小到大排序 oldArr.sort(function(a,b){return a-b}); var minIndex = newArr.indexOf(oldArr[0]); console.log('oldArr',oldArr,'newArr',newArr); // 將距離最近的元素的定位給移動的目標 tagNode.style.top = oItem[minIndex].style.top; tagNode.style.left = oItem[minIndex].style.left; // 把克隆的定位給距離最近的 oItem[minIndex].style.top = cloneNode.style.top; oItem[minIndex].style.left = cloneNode.style.left; //把克隆節點移除 oFather.removeChild(cloneNode); document.onmousemove = null; document.onmouseup = null; } return false; } } </script> </body> </html>
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。