vue-grid-layout元素交换位置及大小
div元素
<grid-layout:layout="map":col-num="10":maxRows="6":row-height="rowHeight":is-draggable="true":is-resizable="true":autoSize="false":is-mirrored="false":vertical-compact="true":preventCollision = "false":margin="[10, 10]":use-css-transforms="true"><grid-item v-for="item in map":x="item.x":y="item.y":w="item.w":h="item.h":i="item.i":key="item.i"@move="moveEvent"@moved="movedEvent"@resized="resizeEvent"class="gridItem"><h1 >{{item.i}}</h1></grid-item></grid-layout>
demo数据:
windowHeight: 0,rowHeight:130,layout: [{ x: 0, y: 0, w: 3, h: 2, i: "0"},{ x: 3, y: 0, w: 4, h: 3, i: "1" },{ x: 7, y: 0, w: 3, h: 2, i: "2" },{ x: 0, y: 2, w: 3, h: 2, i: "10" },{ x: 3, y: 3, w: 4, h: 3, i: "11" },{ x: 7, y: 2, w: 3, h: 2, i: "12" },{ x: 0, y: 4, w: 3, h: 2, i: "20" },{ x: 7, y: 4, w: 3, h: 2, i: "22" },],map:[],curBox:'',
交换的主要方法:
moveEvent(i, x, y) {this.curBox = i},movedEvent(i, x, y){// 1 根据移动位置,循环数据源当前位置是否有元素,不包含自己的位置if (y>11) this.map = JSON.parse(JSON.stringify(this.layout));const item1 = this.layout.find((item) => item.x <= x && x < (item.x+item.w) && item.y <=y && (y < item.y+item.h) && item.i != i);const item2 = this.layout.find((item) => item.i == i);// console.log(item1,item2)item1 && this.changePosition(item1,item2)if(!item1) this.layout = JSON.parse(JSON.stringify(this.map));localStorage.setItem("layout",JSON.stringify(this.layout))},changePosition(item1, item2) {// console.log(item1, item2);// 定义中间变量交换const temp = JSON.parse(JSON.stringify(item1));const temp2 = JSON.parse(JSON.stringify(item2));// 注意:修改的是影响显示的实际数组 map this.layout.forEach((item) => {// 找到 item1,将 item1 的信息换成item2if (item.i === item1.i) {item.x = temp2.x;item.y = temp2.y;item.w = temp2.witem.h = temp2.h}if (item.i === item2.i) {item.x = temp.x;item.y = temp.y;item.w = temp.w;item.h = temp.h;}});// 实现交换后,及时同步 数据映射this.map = JSON.parse(JSON.stringify(this.layout));},
扩展:动态行高、echarts图表动态渲染、指定元素可拖动
动态计算行高:
mounted() {if (localStorage.getItem('layout')){this.layout = JSON.parse(localStorage.getItem('layout'))}this.map = JSON.parse(JSON.stringify(this.layout));localStorage.setItem("layout",JSON.stringify(this.layout))this.onWindowResize()window.addEventListener('resize', this.onWindowResize); // 添加事件监听器},beforeDestroy() {window.removeEventListener('resize', this.onWindowResize); // 移除事件监听器以避免内存泄漏},onWindowResize() {this.windowHeight = window.innerHeight; // 更新窗口高度this.rowHeight = (this.windowHeight-(10*7))/6 //margin的高度*(行数+1)},
echarts图表动态渲染:
//div中,注意data如果是方法中有更新需重新赋值给datalist
<component :is="item.chart" :chart-date="dataList[item.i]"></component>//实际echarts中动态更新视图内容const elementResizeDetectorMaker = require("element-resize-detector");let erd = elementResizeDetectorMaker();
//mounted中(ref对应div绑定的ref)this.$nextTick(() => {erd.listenTo(this.$refs.radarBasic, () => {this.$nextTick(function () {//使echarts尺寸重置this.myChart.resize();});});})
指定元素可拖动:drag-ignore-from=“.draggable” drag-allow-from=“.itemTitle”
<grid-item v-for="item in map":x="item.x":y="item.y":w="item.w":h="item.h":i="item.i":key="item.i"@move="moveEvent"@moved="movedEvent"@resized="resizeEvent"drag-ignore-from=".draggable"drag-allow-from=".itemTitle"class="cardItem_dark cardItem"> <div class="title-top"></div><div class="itemTitle centerItem">{{item.title}}</div><div class="draggable" v-if="['2','4','5','7'].includes(item.i)" :style="'width:'+ 9.3*item.w+'vw;'+'height:'+ (rowHeight*item.h+20*(item.h-1.1))+'px;padding-top:5%'"><component :is="item.chart" :chart-date="dataList[item.i]"></component></div><div class="draggable" v-else :style="'width:'+ 9*item.w+'vw;'+'height:'+ (rowHeight*item.h+20*(item.h-1.1))+'px;padding-top:5px'"><component :is="item.chart" :chart-date="dataList[item.i]"></component></div></grid-item>
参考链接:
Vue Grid Layout - 适用Vue.js的栅格布局系统(项目实例)
Vue Grid Layout -️ 适用Vue.js的栅格布局系统(保姆级使用教程)
Vue Grid Layout 官方文档