基於Vue實現拖拽升級(九宮格拖拽)

前言

在本文中將會用Vue完成九宮格拖拽效果,同時介紹一下網格佈局。具體代碼以及demo能夠點如下超連接進入css

傳送門:Demo以及完整代碼鏈接vue

效果實例

Demo

簡單瞭解Grid佈局(網格佈局)

什麼是網格佈局

CSS網格佈局(又稱「網格」),是一種二維網格佈局系統。CSS在處理網頁佈局方面一直作的不是很好。一開始咱們用的是table(表格)佈局,而後用float(浮動),position(定位)和inline-block(行內塊)佈局,可是這些方法本質上是hack,遺漏了不少功能,例如垂直居中。後來出了flexbox(盒子佈局),解決了不少佈局問題,可是它僅僅是一維佈局,而不是複雜的二維佈局,實際上它們(flexbox與grid)能很好的配合使用。Grid佈局是第一個專門爲解決佈局問題而建立的CSS模塊.

grid

簡單說說網格佈局的屬性

  • display:app

    • grid: 生成塊級網格
    • inline-grid: 生成行內網格
    • subgrid: 若是網格容器自己是網格項(嵌套網格容器),此屬性用來繼承其父網格容器的列、行大小。
  • grid-template-columns佈局

    • 設置網格列大小
  • grid-template-rows學習

    • 設置網格行大小
  • grid-template-areasflex

    • 設置網格區域
  • grid-column-gap動畫

    • 設置網格列間距
  • grid-row-gapthis

    • 設置網格行間距
  • grid-gapflexbox

    • 縮寫形式 grid-gap: <grid-row-gap> <grid-column-gap>
  • justify-itemsspa

    • 水平方向對齊方式(在這裏只是簡單說明)
    • start: 左對齊
    • end: 右對齊
    • center: 居中對齊
    • stretch: 填滿(默認)
  • align-items

    • 垂直方向對齊方式
    • start: 頂部對齊
    • end: 底部對齊
    • center: 居中對齊
    • stretch:填滿(默認)

固然,若是看不懂也沒關係,這裏有一篇我的十分喜歡的網格佈局的文章。裏面介紹得十分詳細。能夠供你們深刻學習網格佈局內容。

傳送門:Grid佈局指南

Vue實現九宮格拖拽

Demo地址: Demo以及完整代碼

實現九宮格佈局

/*css*/

  .container{
    position: relative;   /*實現定位,使得滑塊定位相對於此*/
    display: grid;        /*定義網格佈局*/
    width: 300px;
    height: 300px;
    grid-template-columns: 100px 100px 100px;     /*實現九宮格,行列各三*/
    grid-template-rows: 100px 100px 100px;
    grid-template-areas: "head1 head2 head3"      /*定義個格子的名稱,方便計算*/
                          "main1 main2 main3"
                          "footer1 footer2 footer3";
    border: 1px solid #000;
    margin: 0 auto;
  }
  .block{
    position: absolute;     /*相對於container定位*/
    width: 100px;
    height: 100px;
    display: flex;        /*flex佈局,使得文字在中央*/
    justify-content: center;
    justify-items: center;
    align-items: center;
    align-content: center;
    user-select: none;      /*用戶不可選定文字*/
    background: olivedrab;
    border: 1px solid #000
  }
//app.vue

<div id="app">
  <div class="container">
    <transition >
      <div class="block animated"  :style="{top:this.positionY,left:this.positionX,gridArea:'main2'}" @mousedown="move" ref="block">
        {{positionX}}
        {{positionY}}
      </div>
    </transition>
  </div>
</div>

實現拖拽的JS代碼部分

在這裏我選取一些核心代碼出來說解。代碼有所省略,由於代碼着實有點長,太佔篇幅並且沒多大意義,若是須要瀏覽所有代碼能夠點擊上面的Demo鏈接。

<script>
//引入animate.css 沒有手撕css動畫,直接用了animate.css實現咱們的動畫效果
import animate from 'animate.css';

export default {
  name: 'app',
  data () {
    return {
      positionX:0,      //定義方塊的兩個座標
      positionY:0,
    }
  },
  methods:{
    move(e){
      let oDiv = e.target;      //獲取點擊的目標元素
      let gDiv = e.path[1];     //獲取點擊元素的父級元素
      
      /*獲取點擊時的偏移位置,在這裏要注意一下
      **因爲咱們用的是網格佈局,每在一個格子中相對位置都是相對格子來算的,不是相對於父級盒子左上角
      **也就是說當你把方塊移動到九個格子中任意一個時,方塊的位置都是top:0和left:0
      */
      
      //因此這裏咱們直接取鼠標點擊的位置減去點擊盒子的偏移位置,也就是0
      let disX = e.clientX - 0;     
      let disY = e.clientY - 0;
      document.onmousemove = (e)=>{
      
        //當拖動時,算出的值就恰好是方塊的top和left值
        let left = e.clientX - disX;
        let top = e.clientY - disY;
        switch (oDiv.style.gridArea){
          case "head1 / head1 / head1 / head1":this.rangeOfHead1(left,top,oDiv);break;    //實現head1的移動範圍
          case "head2 / head2 / head2 / head2":this.rangeOfHead2(left,top,oDiv);break;    //實現head2的移動範圍
          case "head3 / head3 / head3 / head3":this.rangeOfHead3(left,top,oDiv);break;    //實現head3的移動範圍
          case "main1 / main1 / main1 / main1":this.rangeOfMain1(left,top,oDiv);break;    //實現main1的移動範圍
          ...
        }
      };
      document.onmouseup = (e)=>{
        //當鼠標擡起時,咱們要作的事
        //經過點擊位置和父級元素的偏移判斷方塊在哪一個區域
        if(e.clientY-gDiv.offsetTop<100&&e.clientX-gDiv.offsetLeft<100){
        
          //將方塊移動到該區域中
          this.changeBlock("head1",oDiv); 
          
        }else if(e.clientY-gDiv.offsetTop>100&&e.clientX-gDiv.offsetLeft<100&&e.clientY-gDiv.offsetTop<200){
          this.changeBlock("main1",oDiv);
        }else if(e.clientY-gDiv.offsetTop>200&&e.clientX-gDiv.offsetLeft<100){
          this.changeBlock("footer1",oDiv);
        }else if(e.clientY-gDiv.offsetTop<100&&e.clientX-gDiv.offsetLeft>100&&e.clientX-gDiv.offsetLeft<200){
          this.changeBlock("head2",oDiv);
        }else if(e.clientY-gDiv.offsetTop<100&&e.clientX-gDiv.offsetLeft>200){
          this.changeBlock("head3",oDiv);
        }else if(e.clientY-gDiv.offsetTop>100&&e.clientX-gDiv.offsetLeft>200&&e.clientY-gDiv.offsetTop<200){
          this.changeBlock("main3",oDiv);
        }else if(e.clientY-gDiv.offsetTop>200&&e.clientX-gDiv.offsetLeft>200){
          this.changeBlock("footer3",oDiv);
        }else if(e.clientY-gDiv.offsetTop>200&&e.clientX-gDiv.offsetLeft>100&&e.clientX-gDiv.offsetLeft<200){
          this.changeBlock("footer2",oDiv);
        }else {
          this.changeBlock("main2",oDiv);
        }
        document.onmousemove=null;      //須要把事件監聽取消
        document.onmousedown = null;    //須要把事件監聽取消
        
        //固然,不能忘記咱們的動畫hhh
        oDiv.className = "block animated wobble";
        let removeClass = setTimeout(()=>{
          oDiv.className = "block animated";
        },500);

      };
    },
    rangeOfHead1(x,y,oDiv){     //判斷head1格子中的能夠移動範圍
      if(x>=200){
        x=200;
      }else if(x<=0){
        x=0;
      }
      if(y>=200){
        y=200;
      }else if(y<=0){
        y=0;
      }
      oDiv.style.left = x + 'px';
      oDiv.style.top = y + 'px';
      this.positionX = x;
      this.positionY = y;

    },
    rangeOfHead2(x,y,oDiv){     //判斷head2格子中的能夠移動範圍
      if(x>=100){
        x=100;
      }else if(x<=-100){
        x=-100;
      }
      if(y>=200){
        y=200;
      }else if(y<=0){
        y=0;
      }
      oDiv.style.left = x + 'px';
      oDiv.style.top = y + 'px';

      this.positionX = x;
      this.positionY = y;

    },
    ...
    changeBlock(blockName,oDiv){    //將方塊移入到對應的區域中
      this.positionX = 0;
      this.positionY = 0;
      oDiv.style.gridArea=blockName;
    }
  },
}
</script>

總結

到這裏咱們把九宮格拖拽實現了,同時學習了Grid(網格佈局)。總的作下來,發現用網格佈局作網格拖拽更加費事,可是爲了後續能夠方便一些,也只好搗鼓下來了。到這裏咱們就把基於Vue的九宮格拖拽實現了,有問題或者發現錯誤的請指正,謝謝你們

珍惜淡定的心境,苦事後更加清

相關文章
相關標籤/搜索