浏览器全屏时 echarts.resize() 无效/滞后解决办法

发布时间 2023-07-10 15:14:47作者: sunshine233

前言

  • echarts 在 dom 上初始化时使用 echarts. init ,这个 dom 是实例容器,一般是一个具有高宽的 DIV 元素。
  • 不能在单个容器上初始化多个 ECharts 实例。 
  • echartsInstance.resize 改变图表尺寸,在容器大小发生改变时需要手动调用
  • echarts.resize() 的核心是监听 id=“myChart” 的那个 div 的尺寸变化,在其发生变化后调用 echarts.resize()。

 一、 布局+样式

因为后面要测试高度变化,所以设定了高度 chartHeight 为变量。(直接写 height:100% 图表不显示)

<template>
  <div id="myChart" :style="{ height: chartHeight + 'px' }"></div>
</template>

<style>
body {
  background-color: lightblue;
}

#myChart {
  width: 90%;
  background-color: lightgoldenrodyellow;
}
</style>

二、js基本代码(vue3 写法)

初始化 mychart 的高度,初始化一个柱状图:

var myChart = null;
const chartHeight = ref(0);
updateChartHeight();

function updateChartHeight() {
  chartHeight.value = window.innerHeight * 0.9;
}

function initEcharts() {
  myChart = echarts.init(document.getElementById('myChart'));
  myChart.setOption({
    title: {
      text: 'ECharts 入门示例'
    },
    tooltip: {},
    xAxis: {
      data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
    },
    yAxis: {},
    series: [
      {
        name: '销量',
        type: 'bar',
        data: [5, 20, 36, 10, 10, 20]
      }
    ]
  });
}

三、监听 echarts 容器尺寸变化(以下简称div)

1. 没有全屏时,div 宽度、高度发生变化

这个很好办,直接用   window.addEventListener("resize", function())  监听就可以。

function windowResize() {
  window.addEventListener("resize", () => {
    updateChartHeight();
    console.log('%c window.innerWidth', "color:blue", window.innerWidth);
    console.log('%c window.innerHeight', "color:blue", window.innerHeight);
    myChart.resize();//改变图表尺寸
  })
}

  效果如图:

 2. 全屏时,div 高度发生变化

解决了高度变化时echarts图表不能正确自适应问题后可知,从非最大化-->全屏,宽度、高度均发生变化,且均无问题。)

 浏览器从“最大化--> 全屏”时,宽度不发生变化,只有高度变化,如图:

 从理论上讲,浏览器按 F11 进入的全屏既然可以被 window.addEventListener("resize")监听到,id="myChart" 的div尺寸也变化了,myChart.resize() 也调用了,那么图表就该正常自适应。

但是由实际情况可知,图表的高度变化和div的高度变化不是同步的,而是滞后了。从非全屏-->全屏,图表没变大;从全屏-->非全屏,图表是全屏时的尺寸。

解决办法:

1. 把 div 的高度单位改成 vh: https://juejin.cn/post/7083382244307370014

<div id="myChart"></div>

#myChart {
  width: 90%;
  height: 80vh;
  background-color: lightgoldenrodyellow;
}

 2. 用 ResizeObserver 监听DOM元素尺寸的变化,在监测到变化后调用 myChart.resize();

function windowResize() {
  window.addEventListener("resize", () => {
    updateChartHeight();//这里只修改div高度
    console.log('%c window.innerWidth', "color:blue", window.innerWidth);
    console.log('%c window.innerHeight', "color:blue", window.innerHeight);
  })
}

function watchEchart() {
  const myChartSize = document.getElementById("myChart");
  var ro = new ResizeObserver(entries => {
    for (let entry of entries) {
      const cr = entry.contentRect;
      console.log('myChart Element:', entry.target);
      console.log(`%c myChart Element  w:${cr.width}px  h:${cr.height}px`, "color:red");
      
       myChart.resize();//监测到div尺寸变化后调用
    }
  });
  ro.observe(myChartSize);
}

 用 ResizeObserver 解决全部代码如下(展开查看):

<script setup>
import { ref, onMounted } from 'vue';
import * as echarts from 'echarts';

var myChart = null;
const chartHeight = ref(0);
updateChartHeight();

onMounted(() => {
  initEcharts();
  windowResize();
  watchEchart();
})
function updateChartHeight() {
  chartHeight.value = window.innerHeight * 0.9;
}

function initEcharts() {
  myChart = echarts.init(document.getElementById('myChart'));
  myChart.setOption({
    title: {
      text: 'ECharts 入门示例'
    },
    tooltip: {},
    xAxis: {
      data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
    },
    yAxis: {},
    series: [
      {
        name: '销量',
        type: 'bar',
        data: [5, 20, 36, 10, 10, 20]
      }
    ]
  });
}

function windowResize() {
  window.addEventListener("resize", () => {
    updateChartHeight();//这个必须放在这里
    console.log('%c window.innerWidth', "color:blue", window.innerWidth);
    console.log('%c window.innerHeight', "color:blue", window.innerHeight);
    // console.log("%c windowResize chartHeight ", "color:blue", chartHeight.value);
  })
}

function watchEchart() {
  const myChartSize = document.getElementById("myChart");
  var ro = new ResizeObserver(entries => {
    for (let entry of entries) {
      const cr = entry.contentRect;
      // console.log('myChart Element:', entry.target);
      console.log(`%c myChart Element  w:${cr.width}px  h:${cr.height}px`, "color:red");
      chartResize();
    }
  });
  ro.observe(myChartSize);
}

function chartResize() {
  myChart.resize();
}

</script>

<template>
  <div id="myChart" :style="{ height: chartHeight + 'px' }"></div>
</template>

<style>
body {
  background-color: lightblue;
}

#myChart {
  width: 90%;
  background-color: lightgoldenrodyellow;
}
</style>
View Code

 效果图如下: