相信有不一樣志已經使用過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