vue中使用echarts图表自适应大小及在modal使用echarts

 主要解决思路:

获取图表节点的父级节点宽度然后赋值给图表节点,父级节点可设置成自适应宽度,然后再modal渲染图标一定要注意节点渲染顺序,最后通过浏览器窗口的resize()事件与echarts的resize()方法来结合控制图表大小

 以UI框架iview为例,element同理,当我们在使用echarts图表时很多情况下宽度都不是固定,这时我们可能会想到用百分比来解决,然后实际并没用,比如我们设置宽度100%,让他随父级元素自适应大小,结果宽度却直接变成了100px,所以直接设置百分比是没有效果的,这时我们可以使用

this.$refs["myChart"].parentNode.offsetWidth//获取父DOM节点的宽度

此方法可以获取DOM节点的父节点宽度,然后父节点可以设置成自适应的百分比或者其他方式如框架中的row>col栅格布局,由于此方法获取的宽度是像素,这样我们就可以直接赋值给echarts图表节点,赋值时记得拼接单位px

this.$refs["myChart"].style.width = `${width}px`;//width为父节点宽度,由于获取的是数值所以需要拼接单位,不然无效

那么重点来了,由于在此案例中我的echarts图表是放在modal对话框中的,而一开始modal节点一般是隐藏状态,如果底层用的是v-if就会涉及到DOM渲染先后的问题,如果还没有渲染之前就是使用DOM.parentNode.offsetWidth方法是获取不到的节点的宽度的,只能获取到一个0,但是翻看框架源代码之后发现是用的v-show也就是隐藏显示不涉及到DOM渲染,经过一番排查之后确认问题还是出在DOM渲染先后这里,所以我们在获取图表节点的时候得加一个异步回调函数定时器、$nexttick都可以,来确保他在渲染之后才获取父节点的宽度,而打开modal的地方也一样,需要加一个异步回调,来确保先打开再渲染

index.vue代码:

    watch: {
    detailModalState(status){
      if(!status){
        this.$refs["marketingDeatalRef"].destroy();
      }
    }
  },

// 查看modal方法
lookDetail() {
      this.detailModalState = true//此处要确保先打开modal再渲染
      this.$nextTick(()=>{
        this.$refs['marketingDeatalRef'].initCharts()//初始化图表的方法
      })
    },

modal.vue代码:

   initCharts(){
        this.$refs["lineEchartRef"].init();
    }
//注意此方法非生命周期
  destroy() {
      this.$refs["lineEchartRef"].destroy();
    },

echarts.vue代码:

<template>
  <div ref="myChart" :style="{ height: '400px' }"></div>
</template>

<script>
import * as echarts from "echarts";
export default {
  name: "",
  data() {
    return {
      resizeFn:null,
    };
  },
  mounted() {},
  methods: {
    init() {
      this.$nextTick(() => {
        let myChartDom = this.$refs["myChart"];
        let width = this.$refs["myChart"].parentNode.offsetWidth; //获取父级节点的宽度
        myChartDom.style.width = `${width}px`;//赋值给图表DOM
      });
      let myChart = echarts.init(this.$refs["myChart"]);
      myChart.setOption({
        title: {
          text: "",
        },
        tooltip: {
          trigger: "axis",
        },
        legend: {
          data: ["日新增客户数", "活动参与客户数", "完成任务客户数"],
        },
        grid: {
          left: "0%",
          right: "0%",
          bottom: "3%",
          containLabel: true,
        },
        toolbox: {
          feature: {
            saveAsImage: {},
          },
        },
        xAxis: {
          type: "category",
          boundaryGap: true,
          data: [
            "2022-08-25",
            "2022-08-26",
            "2022-08-27",
            "2022-08-28",
            "2022-08-29",
            "2022-08-30",
            "2022-08-31",
          ],
        },
        yAxis: {
          type: "value",
        },
        series: [
          {
            name: "日新增客户数",
            type: "line",
            stack: "Total",
            data: [120, 132, 101, 134, 90, 230, 210],
          },
          {
            name: "活动参与客户数",
            type: "line",
            stack: "Total",
            data: [220, 182, 191, 234, 290, 330, 310],
          },
          {
            name: "完成任务客户数",
            type: "line",
            stack: "Total",
            data: [150, 232, 201, 154, 190, 330, 410],
          },
        ],
      });
      this.resize = () => {//中转一下
        let width = this.$refs["myChart"].parentNode.offsetWidth; 
        // myChartDom.style.width = `${width}px`;//可以直接赋值然后再调用echarts的resize方法
        myChart.resize({ width: width + "px", height: "400px" }); //resize方法可以重设图表大小,可以传参设置
      }
      window.addEventListener("resize", this.resizeFn);//添加浏览器窗口大小变化事件,resize名字是固定的
    },
    // 为什么放在一个事件内而不是放在生命周期内,因为关闭modal的时候modal节没了获取不到节点大小,再调整窗口大小会报父级节点不可读的错误
    // 通过监听modal状态来调用此方法
    //注意此方法非生命周期钩子
    destroy(){
      //移除添加的resize事件,如果不移除这个事件会一直在,然后在其他页面调整窗口大小时会报错,关闭modal之后再调整窗口也会报错
      window.removeEventListener("resize",this.resizeFn);
    }
  },
  
};
</script>

<style lang="less" scoped>
</style>

初始化大小:

缩放后:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值