欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

原生js實現(xiàn)九宮格拖拽換位

 更新時間:2021年01月26日 10:59:12   作者:_小木不是木_  
這篇文章主要為大家詳細介紹了原生js實現(xiàn)九宮格拖拽換位,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

使用原生JS寫出一個九宮格,實現(xiàn)九個格子何以拖拽換位的效果,供大家參考,具體內(nèi)容如下

效果演示

具體思路分析和代碼:

圖解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,樣式設(shè)置:在樣式里最好使用定位來布局,不然以后拖拽代碼會麻煩點兒。
    (這里沒有設(shè)置父容器的具體位置,如果設(shè)置了父容器的具體位置,則在移動
    時top和left的值需要根據(jù)情況計算位置)
   2,父容器盒子里的內(nèi)容最好使用js代碼來生成,方便使用和添加樣式
    2-1:(循環(huán)生成子元素)
     我們子元素使用的定位布局,不難發(fā)現(xiàn):每行的top值一樣,每列的left值一樣,因此循環(huán)生
     成子元素我們可以使用3*3的循環(huán)嵌套來寫,這樣就可以講每行的樣式設(shè)置了。
    2-2:(給循環(huán)生成的標簽添加隨機顏色和文字)
     隨機顏色我是用的時rgb()來實現(xiàn)的,文字可以使用ASCII碼來生成,也可以使用字符串拼接
     來生成,我這里使用ASCII碼生成。
    PS:這樣我們的基本樣式就設(shè)置完畢了,接下來就是設(shè)置拖拽的事件
   3,給每一個元素添加事件,這里我們需要三個事件: onmousedown - onmousemove - onmouseup
    3-1:(首先是按下事件 onmousedown)
     當我們在對應子元素按下時,我們要獲取鼠標到按下目標邊框線內(nèi)的距離,并且克隆這個元素,
     將這個元素扔到父容器里面充當占位,(這里注意,克隆的這個節(jié)點在HTML結(jié)構(gòu)里是放到最后
     的,如果不處理后面會出BUG?。。。?。
    3-2:(然后處理移動事件 onmousemove)
     在按下子元素塊兒并且移動時,我們要給目標設(shè)置他的top和left值,來實現(xiàn)跟隨移動,所以
     我們需要獲取鼠標到可視窗口的距離,目標的top和left值 = 鼠標到可視窗口的距離 - 鼠標
     到目標邊緣的距離(這里無邊框,如果有需要額外減去邊框?qū)挾龋?
     PS: 
      這里存在一個BUG!?。。≡谕献r,存在一個默認事件--選中文字,當你松開之后,目
      標還會跟著走,就算你關(guān)閉了onmousemove這個事件。所以這里需要阻止一下默認事件。
    3-3:(最后處理抬起事件 onmouseup)這里也是最重要的一步!?。?!
     核心思想:
       當鼠標抬起時,我們要計算當前移動目標的中心點和每一個子元素中心點的距離,
       哪一個離得最近,和哪個交換位置(注意,這里存在一個BUG,這里的BUG就是
        3-1 里提到的BUG,需要提前處理)。
     具體過程:
      3-3-1:
       首先我們要進行循環(huán),計算拖拽目標的中心點與每一個子元素的中心點的距離,具體
       參照 圖解1 。 (拖拽目標距離可視窗口的左邊距 - 子元素距離可視窗口的左邊
       距)平方 + (拖拽目標距離可視窗口的上邊距 - 子元素距離可視窗口的上邊距)
       平方。最后在開方,得到中心點的距離(注意3-1的BUG要處理掉,把,要把移動的
       標簽放到結(jié)構(gòu)的最后,然后循環(huán)的時候?qū)⑺懦簦蝗幻看尉嚯x最近的都是它本身)。
      3-3-2:
       我們循環(huán)會得到我們想要的每一個距離,然后將這些距離放到一個數(shù)組里,并且再定
       義一個數(shù)組備份一下,方便對照具體是哪個標簽。
       將其中一個數(shù)組進行排序,然后再備份數(shù)組中查一下最小的值在備份數(shù)組中的索引下
       標,這個索引下標也就是對應的子元素了。
      3-3-3:
       然后將距離最近的子元素的 left和top值給 目標元素
       然后將克隆的標簽的 left和top值給 距離最近的子元素
       最后在將克隆的標簽移除掉

       這里還是會有一個BUG?。?!如果不在標簽上按 直接抬起鼠標的話,會報錯,這是因
       為直接執(zhí)行了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 循環(huán)生成子元素div,并給他們設(shè)置定位值
  // 設(shè)定固定的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');//創(chuàng)建子元素
    oFather.appendChild(oDiv);
    oDiv.style.left = j * (oDiv.offsetWidth + mL) +'px';
    oDiv.style.top = i * (oDiv.offsetHeight + mT) +'px';
    // 隨機顏色設(shè)置
    oDiv.style.background = 'rgb('+parseInt(Math.random()*256) + "," +parseInt(Math.random()*256) + ","+parseInt(Math.random()*256)+')';
    // 加上字母
    oDiv.innerText = String.fromCharCode(asc++);
   }
  }
  // 為了方便理解,將事件寫到了外面,這里可以生成標簽循環(huán)內(nèi)部
  /* var oItem = document.querySelectorAll('.father>div');
  這種方式獲取的是靜態(tài)集合,只會獲取到初次頁面加載的內(nèi)容,用這種辦法獲取子元素會出BUG */
  var oItem = oFather.children;
  for(var k = 0 ;k<oItem.length; k++){
   oItem[k].onmousedown = function(e){
    var evt = e || event;
    // 獲取鼠標到目標邊框內(nèi)的距離
    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;

     //把克隆節(jié)點移除
     oFather.removeChild(cloneNode);

     document.onmousemove = null;
     document.onmouseup = null;
    }
    return false;
   }
  }
 </script>
</body>
</html>

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論