当前位置: 首页 > Web前端 > vue.js

vue-grid-layout拖拽布局添加新元素

时间:2023-03-31 19:50:22 vue.js

场景项目遇到了dashboard做报表,每张卡片就是一个报表,有不同类型的报表,每种类型都有其特定的大小。允许选择报告并将其添加到仪表板。允许通过拖放调整每张卡片的位置和大小。最后,可以保存仪表板的布局。遇到的问题vue-grid-layout是通过维护一个数组(layout)来实现拖拽布局的。每张卡片都是一个item,每个item包含坐标、宽高等信息。因此,在添加卡片时,在数组中添加一项即可,但新项的坐标始终为(0,0),会挤走已经布置好的卡片,无法选择一个可以容纳卡片的空间来添加新元素。解决方案卡片对象有如下属性,其中x,y,w,h是关键信息,用来记录卡片的位置和大小,i是卡片的id。添加时需要保证不会出现重复的卡片。minW和minH用于指定卡片的最小尺寸,type用于标记卡片的类型。//卡片对象{"i":"card1","x":0,"y":0,"w":4,"h":2,"minW":3,"minH":2,"type":"typeA"}通过选择一个可以容纳卡片的空间来添加卡片,实际上是根据已有的布局(layout)和新卡片的大小计算新卡片的坐标(x和y)卡(w和h)。.可以分为以下几个步骤:初始化新元素:创建一个新的卡片元素,需要包含布局所需的所有属性,最好继承创建卡片的所有其他属性。确定布局边界:确定卡片允许添加的区域范围生成地图:使用二维数组生成地图,根据布局标记地图的占用申请位置:遍历地图,根据新元素的大小在地图上申请一个位置,当满足其要求的大小有空隙时,插入到具体实现中/*新元素方法**/functionaddItem(item,itemId,layout){//初始化元素letnewItem={...item,"i":itemId,"x":0,"y":0,"w":item.w,"h":item.h}//确定边界letYs=[],maxX=0,maxY=0,edgeX=0,edgeY=0布局。地图(它em=>{Ys.push(item.y+item.h)})maxY=Ys.length&&Math.max.apply(null,Ys)||1edgeX=12edgeY=maxY//使用二维数组生成mapletgridMap=newArray()for(letx=0;x{//将布局中卡片占据的区域标记为1for(letx=item.x;x<(item.x+item.w);x++){for(lety=item.y;y<(item.y+item.h);y++){gridMap[x][y]=1}}})//遍历地图并申请位置for(lety=0;y=item.w&&edgeY-y>=item.h){letitemSignArr=[]for(leta=x;a<(x+item.w);a++){for(让b=y;b<(y+item.h;b++)){itemSignArr.push(gridMap[x][y])}}if(itemSignArr.indexOf(1)<0){newItem.x=xnewItem.y=ylayout.push(newItem)return}}}}//不满足条件newItem.x=0newItem.y=edgeY+1layout.push(newItem)}这个方法的关键是applyforspace:遍历地图上的每个格子时,首先需要判断剩余的横向和纵向空间是否可以容纳卡片。如果没有,直接跳出,在布局边界的最后一行添加元素。如果可以容纳,则检查新元素所需空间的每个格子是否被占用(地图gridMap中标记“1”被占用),这里用一个数组itemSignArr记录占用情况。如果这个数组中没有出现“1”,则说明所需空间为“空”,可以重新插入卡片。否则,转到下一个网格并重复应用过程。相关阅读vue-grid-layout文档