使用 vue-grid-layout + echart 实现图形可拖拽式布局+自适应大小

学习目标:

实现 echart 表在网页中的可拖拽式布局+自适应大小


学习内容:

  1. 安装 vue-grid-layout
  2. 安装 echart
  3. 编写一个 echart 折线图组件
  4. 设置 echart 自适应大小

一、安装 echart

  1. 切到 vue-cli 目录下执行一下命令

    此命令将为为你在本项目下安装 vue-grid-layout

    npm install vue-grid-layout --save
    
  2. 编写放置 vue-grid-layout 的组件

    引入 vue-grid-layout 的两个组件 GridLayout, GridItem 并注册

    <script>
      import { GridLayout, GridItem } from "vue-grid-layout" //引入组件
      export default {
        name: 'VueGirdLayout',
        components:{    //注册组件
          GridLayout,
          GridItem
        }
      }
    </script>
    

    在页面上放入组件

    <template>
      <div>
        <h1>vue-grid-layout可拖拽式布局</h1>
        <grid-layout :layout.sync="layout"
                     :col-num="12"
                     :row-height="30"
                     :is-draggable="draggable"
                     :is-resizable="resizable"
                     :vertical-compact="true"
                     :use-css-transforms="true"
        >
            <grid-item v-for="item in layout"
              :static="item.static"
              :x="item.x"
              :y="item.y"
              :w="item.w"
              :h="item.h"
              :i="item.i"
              :key="item.i"
            >
              <span class="text">{{item.i}}</span>
            </grid-item>
        </grid-layout>
      </div>
    </template>
    
    <script>
      import { GridLayout, GridItem } from "vue-grid-layout" //引入组件
    
      export default {
        name: 'VueGirdLayout',    //注册组件 
        components:{
          GridLayout,
          GridItem
        },
        data() {
            return {
                layout: [ //每一个 grid-item 的属性
                    {"x":0,"y":0,"w":4,"h":4,"i":"0", static: false},
                    {"x":2,"y":0,"w":5,"h":5,"i":"1", static: false},
                    {"x":4,"y":0,"w":6,"h":6,"i":"2", static: false},
                ],
                draggable: true, //是否可拖拽
                resizable: true, //是否可更改大小
            }
        },
      }
    </script>
    
    <style>
      .vue-grid-layout {
        background: #eee;
      }
      .vue-grid-item:not(.vue-grid-placeholder) {
          background: rgb(255, 255, 255);
          border: 1px solid black;
      }
      .vue-grid-item .static {
          background: #cce;
      }
    </style>
    

    layout 数组的数据为 GridItem 组件的属性
    “x”、"y"表示为 GridItem 组件的坐标,“w”、“h” 表示为 GridItem 组件的宽和高,"i"表示为 GridItem 组件的id,“static” 表示为单个 GridItem 组件是否可被拖拽。

    此时该组件的页面应该为下图所示
    在这里插入图片描述

图1-1 vue-grid-layout 引入后的画面

二、安装echart

  1. 在 vue-cli 目录下执行以下命令

    此命令在此项目下安装 echart

    npm install echarts --save
    
  2. 引入 echart
    我们仅需要在使用到 echart 图的的组件中引用 echart
    创建一个折线图组件 LineChart.vue

    <template>
      
    </template>
    
    <script>
        import * as echarts from 'echarts' //引入图标
    
        export default {
            name:'LineChart' //命名组件
        }
    </script>
    
    <style>
    
    </style>
    

三、编写 echart 折线图组件

  1. 写入一个折线图

    <template>
        <div ref="MyChartDom" :style="{width: '100%', height: '100%'}"></div>
    </template>
    
    <script>
        import * as echarts from 'echarts' //引入图标
    
        export default {
            name:'LineChart', //命名组件
            data() {
                return {
                    option:{ //创建折线图的配置项数据
                        xAxis: {
                            type: 'category',
                            data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
                        },
                        yAxis: {
                            type: 'value'
                        },
                        series: [
                            {
                            data: [150, 230, 224, 218, 135, 147, 260],
                            type: 'line'
                            }
                        ]
                    },
                    ChartDom:null,
                    MyChart:null
                }
            },
            methods: {
                CreateChart(){
                    this.ChartDom = this.$refs.MyChartDom // 获取到你防止echart的Dom
                    this.MyChart = echarts.init(this.ChartDom) // 实例化你的 echart 图
                    this.MyChart.setOption(this.option)
                    setTimeout (()=>{ //由于网格布局拖拽放大缩小图表不能自适应,这里设置一个定时器使得echart加载为一个异步过程
                        this.$nextTick(() => {
                            this.MyChart.resize()
                        })
                    },0)
                }
            },
            mounted() { // 页面初始化后执行
                this.CreateChart()
            },
        }
    </script>
    
    <style>
    
    </style>
    
    1. 将在之前创建的 vue-grid-layout 中引用刚刚写的折线图组件

      引入折线图组件

      import LineChart from "./LineChart.vue"
      

      注册折线图组件

      components:{
            GridLayout,
            GridItem,
            LineChart
      },
      

      引用折线图组件
      将 grid-item 标签下的 span 标签替换为折线图组件

    <template>
      <div>
        <h1>vue-grid-layout可拖拽式布局</h1>
        <grid-layout :layout.sync="layout"
                     :col-num="12"
                     :row-height="30"
                     :is-draggable="draggable"
                     :is-resizable="resizable"
                     :vertical-compact="true"
                     :use-css-transforms="true"
        >
            <grid-item v-for="item in layout"
              :static="item.static"
              :x="item.x"
              :y="item.y"
              :w="item.w"
              :h="item.h"
              :i="item.i"
              :key="item.i"
            >
              <LineChart/>
            </grid-item>
        </grid-layout>
      </div>
    </template>
    

    此时页面应该为如下图所示
    在这里插入图片描述

图3-1 echart 引入到 vue-grid-layout 的画面
此时成功引入了之前写的折线图但是却不能自适应 grid-item 的大小。

echart 不能自适应大小

四、设置 echart 自适应大小

我们的思路是在 echart 组件中创建一个调整大小的函数,每当 vue-grid-layout 组件中的 grid-item 大小改变时调用 echart 组件的函数。

  1. 在 echart 组件中编写调节 echart 大小的函数

    在echart 组件中 methods 中创建一个 sizechange() 函数

    methods: {
            CreateChart(){
                this.ChartDom = this.$refs.MyChartDom // 获取到你防止echart的Dom
                this.MyChart = echarts.init(this.ChartDom) // 实例化你的 echart 图
                this.MyChart.setOption(this.option)
                setTimeout (()=>{ //由于网格布局拖拽放大缩小图表不能自适应,这里设置一个定时器使得echart加载为一个异步过程
                    this.$nextTick(() => {
                        this.MyChart.resize()
                    })
                },0)
            },
            sizechange(){ // 修改 echart 大小
                this.MyChart.resize() 
            }
    }
    
  2. 在 vue-grid-layout 组件中当改变 grid-item 大小时调用 echart 组件的sizechange()函数

    在父组件中的 grid-item 设定当大小改变时执行某个函数

    <template>
      <div>
        <h1>vue-grid-layout可拖拽式布局</h1>
        <grid-layout :layout.sync="layout"
                     :col-num="12"
                     :row-height="30"
                     :is-draggable="draggable"
                     :is-resizable="resizable"
                     :vertical-compact="true"
                     :use-css-transforms="true"
        >
            <grid-item v-for="item in layout"
              :static="item.static"
              :x="item.x"
              :y="item.y"
              :w="item.w"
              :h="item.h"
              :i="item.i"
              :key="item.i"
              @resize="SizeAutoChange(item.i)"  
            >  <!-- 当 grid-item 改变时执行 SizeAutoChange() 函数  -->
              <LineChart :ref="`LineChart${item.i}`"/> <!-- 设定好 ref 使得下面操控的是某个子组件的函数 -->
            </grid-item>
        </grid-layout>
      </div>
    </template>
    

    在父组件中创建一个函数调用子组件 的函数SizeAutoChange()

    methods: {
          SizeAutoChange(ChartId){
            var EchartId = `LineChart${ChartId}` // 拿到子组件实力对象
            eval(`this.$refs.${EchartId}[0].sizechange()`) //执行子组件的函数
          }
    }
    

    此时折线图就可以根据 grid-item 拖拽后的大小进行自适应了

chart 根据父元素自适应大小

完整代码

父组件 VueGirdLayout.vue 部分

<template>
  <div>
    <h1>vue-grid-layout可拖拽式布局</h1>
    <grid-layout :layout.sync="layout"
                 :col-num="12"
                 :row-height="30"
                 :is-draggable="draggable"
                 :is-resizable="resizable"
                 :vertical-compact="true"
                 :use-css-transforms="true"
    >
        <grid-item v-for="item in layout"
          :static="item.static"
          :x="item.x"
          :y="item.y"
          :w="item.w"
          :h="item.h"
          :i="item.i"
          :key="item.i"
          @resize="SizeAutoChange(item.i)" 
        >  <!-- 当 grid-item 改变时执行 SizeAutoChange() 函数  -->
          <LineChart :ref="`LineChart${item.i}`"/> <!-- 设定好 ref 使得下面操控的是某个子组件的函数 -->
        </grid-item>
    </grid-layout>
  </div>
</template>

<script>
  import { GridLayout, GridItem } from "vue-grid-layout" //引入组件
  import LineChart from "./LineChart.vue"

  export default {
    name: 'VueGirdLayout',    //注册组件 
    components:{
      GridLayout,
      GridItem,
      LineChart
    },
    data() {
        return {
            layout: [ //每一个 grid-item 的属性
                {"x":0,"y":0,"w":4,"h":4,"i":"0", static: false},
                {"x":2,"y":0,"w":5,"h":5,"i":"1", static: false},
                {"x":4,"y":0,"w":6,"h":6,"i":"2", static: false},
            ],
            draggable: true, //是否可拖拽
            resizable: true, //是否可更改大小
        }
    },
    methods: {
      SizeAutoChange(ChartId){
        var EchartId = `LineChart${ChartId}` // 拿到子组件实力对象
        eval(`this.$refs.${EchartId}[0].sizechange()`) //执行子组件的函数
      }
    },
  }
</script>

<style>
  .vue-grid-layout {
    background: #eee;
  }
  .vue-grid-item:not(.vue-grid-placeholder) {
      background: rgb(255, 255, 255);
      border: 1px solid black;
  }
  .vue-grid-item .static {
      background: #cce;
  }
</style>

子组件 LineChart.vue 部分

<template>
    <div @click="sizechange" ref="MyChartDom" :style="{width: '100%', height: '100%'}"></div>
</template>

<script>
    import * as echarts from 'echarts' //引入图标

    export default {
        name:'LineChart', //命名组件
        data() {
            return {
                option:{ //创建折线图的配置项数据
                    xAxis: {
                        type: 'category',
                        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
                    },
                    yAxis: {
                        type: 'value'
                    },
                    series: [
                        {
                        data: [150, 230, 224, 218, 135, 147, 260],
                        type: 'line'
                        }
                    ]
                },
                ChartDom:null,
                MyChart:null
            }
        },
        methods: {
            CreateChart(){
                this.ChartDom = this.$refs.MyChartDom // 获取到你防止echart的Dom
                this.MyChart = echarts.init(this.ChartDom) // 实例化你的 echart 图
                this.MyChart.setOption(this.option)
                setTimeout (()=>{ //由于网格布局拖拽放大缩小图表不能自适应,这里设置一个定时器使得echart加载为一个异步过程
                    this.$nextTick(() => {
                        this.MyChart.resize()
                    })
                },0)
            },
            sizechange(){ // 修改 echart 大小
                this.MyChart.resize() 
            }
        },
        mounted() { // 页面初始化后执行
            this.CreateChart()
        }
    }
</script>

<style>

</style>
  • 17
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值