vue-grid-layout 添加組件心得

相信有不一樣志已經使用過vue-grid-layout這個插件了,對於界面化拖拽佈局操做起來仍是很是友好的css

前幾天看到一個項目,要在此基礎上優先添加到空白位置。vue

vue-grid-layout插件自己能夠經過對數組數據的push,進行添加數據,但必要的 x , y , w , h , i 是必須的。c++

固然,你能夠對 x 和 y 強行賦 0 , 他爲將此區域內的基本項順序往下擠。可我想個人是有空缺且可以放下時,優先使用空缺位置,沒有空缺時,從上住下順序添加。數組

<template>
  <div id="gridPage">
    <h1>grid</h1>
    <div class="btnGroup">
      <button @click="addItem">add</button>
    </div>
    <div class="view">
      <grid-layout
        :layout.sync="layout"
        :col-num="layoutColNum"
        :row-height="10"
        :is-draggable="true"
        :is-resizable="true"
        :is-mirrored="false"
        :vertical-compact="true"
        :margin="[10, 10]"
        :use-css-transforms="true"
        @layout-updated="layoutUpdatedEvent"
        @layout-ready="layoutReadyEvent"
        >
        <grid-item v-for="(item,idx) in layout"
          class="item"
          :x="item.x"
          :y="item.y"
          :w="item.w"
          :h="item.h"
          :i="item.i"
          :key="idx">
            {{item.i}}|{{idx}}
        </grid-item>
      </grid-layout>
    </div>
  </div>
</template>
<style lang="less">
  #gridPage{
    >h1{
      font-size: 16px;
    }
    >.view{
      border: 1px solid #000;
      .item{
        background-color: #aaa;
      }
    }
  }
</style>
<script>
import VueGridLayout from 'vue-grid-layout';

export default {
  name: 'girdPage',
  data: function (){
    return {
      // 佈局位置數據
      layout: [],
      // 佈局二維數組地圖
      layoutMap: [],
      // 佈局列數
      layoutColNum: 50
    }
  },
  methods: {
    // 添加項目
    addItem: function () {
      // 產生隨機寬高
      var itemW = this.rnd(5,10);
      var itemH = this.rnd(5,10);
      var addItem = {
        "x": 0,
        "y": this.layoutMap.length,
        "w": itemW,
        "h": itemH,
        "i": this.layout[this.layout.length-1]?parseInt(this.layout[this.layout.length-1].i)+1:0
      };
      if(this.layoutMap.length){
        // console.log(this.layoutMap.length);
        for(let r = 0 , rLen =this.layoutMap.length ; r < rLen; r++){
          for(let c = 0; c <= (this.layoutColNum-itemW); c++){
            let res = this.regionalTest(
              c, 
              r, 
              itemW, 
              rLen>(r+itemH)?itemH:rLen-r
              );

            if(res.result){
              // 更新添加數據內容
              addItem = {
                "x": res.x,
                "y": res.y,
                "w": itemW,
                "h": itemH,
                "i": parseInt(this.layout[this.layout.length-1].i)+1
              };

              c = this.layoutColNum+1;
              r = rLen+1;
            }else{
              c = res.offsetX;
            }
          }
        }
      }
      // 更新二維數組地圖
      for(let itemR = 0 ; itemR < itemH ; itemR++){
        for(let itemC = 0 ; itemC < itemW ; itemC++){
          // 若是沒有該行,初始化
          if(!this.layoutMap[addItem.y+itemR]){
            this.layoutMap[addItem.y+itemR] = new Array(this.layoutColNum);
            for(let i = 0 ;i < this.layoutColNum ; i++){
              this.layoutMap[addItem.y+itemR][i] = 0;
            }
          }
          // 標記點
          this.layoutMap[addItem.y+itemR][addItem.x+itemC] = 1;
        }
      }
      
      // console.log(this.layoutMap);
      // 添加數據
      this.layout.push(addItem);

    },
    // 生成二維數組地圖
    genereatePlaneArr: function (data) {
      var map = [];
      if(Array.isArray(data)){
        for(var i = 0; i<data.length; i ++){
          var one = data[i];
          // 循環行
          for(var r = one.y ; r < ( one.y + one.h ) ; r++){
            // 循環列
            for(var c = one.x ; c < ( one.x + one.w) ; c++){
              // 檢修當前行是否存在 
              if(!map[r]){
                map[r] = new Array(this.layoutColNum);
                
                for(let i = 0 ; i < this.layoutColNum ; i++){
                  map[r][i] = 0;
                }
              }
              // 佔據爲1
              map[r][c] = 1;
            }
          }
        }
      }
      return map;
    },
    // 區域檢測 x,y 二維數據地圖起始座標點  w,h 檢測區域寬高
    regionalTest: function (x,y,w,h) {
      // 定義返回 x,y 偏移 及 是否有空位置
      let offsetX = 0,offsetY = 0,res = true;
      // 按區域循環檢測 二維數組地圖
      for(let r = 0; r < w ;r++){
        for(let c = 0; c <= h ;c++){
          let point = this.layoutMap[y+r]?this.layoutMap[y+r][x+c]:0;
          // 如該點被佔據 記錄偏移值
          if(point===1){
            res = false;
            offsetX = offsetX>(x+c)?offsetX:x+c;
            offsetY = offsetY>(y+r)?offsetY:y+r;
          }
        }
      }

      return {
        result: res,
        offsetX: offsetX,
        x: x,
        y: y
      };
    },
    // 組件更新完成生命週期
    layoutReadyEvent: function(newLayout) {
      // console.log("4Ready");
      // console.log(this.layout);
      // 當插件加載完成後  獲取如今的二維地圖樹
      this.layoutMap = this.genereatePlaneArr(this.layout);
    },
    layoutUpdatedEvent: function(newLayout) {
      // console.log("Updated");
      // console.log(this.layout);
      // 當插件內容佈局發生變化後  獲取如今的二維地圖樹
      this.layoutMap = this.genereatePlaneArr(this.layout);
    },
    rnd: function (m,n) {
      return (Math.random()*(m-n+1)+n)|0;
    }
  },
  components: {
    GridLayout: VueGridLayout.GridLayout,
    GridItem: VueGridLayout.GridItem
  }
}

簡單寫的一個Demo, 不足之處還望指正less

相關文章
相關標籤/搜索