vue-grid-layout 实现类似grafana的可拖拽动态布局

3,149 阅读3分钟

最近产品提出了一个需求,希望页面的图表能像grafana大屏这样可以,可以随意拖拽和缩放。通过审查grafana页面可以发现其css中出现react-grid-layout的样式。随后在网上进行一番搜索后,果然vue也有一套类似的栅格布局系统,大家可以在github上查看其源码和介绍官网链接 ,下面是我结合自己的一个实际应用来介绍在项目中是怎么使用的。

常用配置参数说明

在项目中安装和引入vue-grid-layout后,需要配置grid-layout 与 grid-item中的一些参数。 其中grid-layout中必需要配置的参数是layout。这是数据源,其类型为Array,数组中的每一项必须包含grid-item中所需要的属性,包括:i,x,y,w,h属性。

grid-layout中的参数

参数含义说明
layout数据源每条数据项必须有 i, x, y, w 和 h 属性
colNum表示网格有多少列
rowHeight每行的高度,单位像素
isDraggable标识栅格中的元素是否可拖拽
isResizable标识栅格中的元素是否可调整大小
useCssTransforms表示是否应使用 CSS transition-property: transform,否则是postion定位;
isResizable标识栅格中的元素是否可调整大小

grid-item中的参数

参数含义说明
i栅格元素中的ID 项的唯一标识符
x标识栅格元素位于第几列表示项的初始水平位置
y标识栅格元素位于第几行表示项的初始垂直位置
w表示项的初始宽度值是一个与 colWidth 相乘的数字,假设在layout中设置colNum=12,w+x的和不能超过colNum
h表示项的初始高度值是一个与 rowHeight 相乘的数字

应用

  <grid-layout
      :layout.sync="layoutList"
      :col-num="colNum"
      :row-height="100"
      :is-draggable="true"
      :is-resizable="true"
      :vertical-compact="verticalCompact"
      :margin="[0, 0]"
      :use-css-transforms="false"
      class="hoverStyle">
      <grid-item v-for="item in layoutList" :key="item.i"
                 :x="item.x"
                 :y="item.y"
                 :w="item.w"
                 :h="item.h"
                 :i="item.i">
        <component :is="item.component" ref="com"></component>
      </grid-item>
    </grid-layout>
    
    // data部分
     data(){
    return{
      layoutList:[
        {"x":0,"y":0,"w":12,"h":1,"i":"6",component:'TopTabs',type:'other'},
        {"x":0,"y":1,"w":4,"h":3,"i":"0",component:'LineChart',type:'chart'},
        {"x":4,"y":1,"w":4,"h":3,"i":"1",component:'LineChart2',type:'chart'},
        {"x":8,"y":1,"w":4,"h":3,"i":"2",component:'LineChart4',type:'chart'},
        {"x":0,"y":4,"w":4,"h":3,"i":"3",component:'BarChart',type:'chart'},
        {"x":4,"y":4,"w":4,"h":3,"i":"4",component:'BarChart2',type:'chart'},
        {"x":8,"y":4,"w":4,"h":3,"i":"5",component:'BarChart3',type:'chart'}
      ],
      verticalCompact: true,
      colNum: 12
    }
  },

上面利用vue本身的component is 来动态渲染组件。其中有很多图形是echarts图形,通常我们会指定echarts容器具体的宽高大小,但是在这里是根据我们的配置来决定的,所以在在处理echarts图形时需要注意下面的问题:

与echarts结合使用时需要注意的点

1. 首次加载页面时,echarts图形并不显示

解决方法:echarts图形需要在vue-grid-layout加载完成后才能进行初始化,所以我们需要在echarts加载加上异步

2. gird-item 进行缩放时,echarts图表没有自适应

解决方法:在echarts容器中使用onresize方法,类似window.onresize()。

3. echarts图形在移动时鼠标样式的问题

审查元素时,我们可以看到grid-item是会动态新增样式cursor:move;但是echarts图形并没有生效,为了使echarts图形有相同move样式,我们需要在加载时通过事件监听来设置样式。

  this.echartLine.getZr().on('mousemove',(params)=>{
       let pointInPixel= [params.offsetX, params.offsetY];
       if (this.echartLine.containPixel('grid',pointInPixel)) {//若鼠标滑过区域位置在当前图表范围内 鼠标设置为move
         this.echartLine.getZr().setCursorStyle('move')
       }else{
         this.echartLine.getZr().setCursorStyle('default')
       }
     })
     this.echartLine.getZr().on('mouseup',()=>{
       this.echartLine.getZr().setCursorStyle('default')
     })