总所周知,echarts的自适应有时候会出现各种各样的bug,尤其在添加了多页签缓存后,echarts的自适应问题会更加明显。
在编写代码时,通常会将echarts的父级div的width设置为100%,然后在添加resize()方法进行页面的自适应。这种方式在react项目的普通页面中是可以正常使用的,但是在添加了多页签缓存后,就会出现在一个页签中改变分辨率,再恢复,另一个页面中的echarts图无法自适应的问题。
在经过一系列排查后,终于找到了问题的关键所在,这是因为没有添加多页签缓存页面时,一旦切换页面,页面上的各种元素被卸载,再次进入时再次加载,但是加入多页签缓存之后的页面再次进入时元素不会重新加载,并且这时echarts的宽度会失效,被识别为100px。为了解决这一问题,我尝试了各种各样的方法,最终成功将这问题解决,以下是我成功之后的代码。
import React, { useEffect, useState, useRef } from 'react';
import * as echarts from 'echarts';
const evaChart = ({ chartData }) => {
const ref = useRef(null);
const sort = (chartData) => {
//柱状图数据排序
for (let i = 0; i < chartData.length; i++) {
for (let j = i + 1; j < chartData.length; j++) {
if (Number(chartData[i].count) < Number(chartData[j].count)) {
let a = chartData[i];
chartData[i] = chartData[j];
chartData[j] = a;
}
}
}
};
useEffect(() => {
if (chartData && chartData.length != 0) {
let xData = [];
let yData = [];
chartData.forEach((item) => {
xData.push(item._id);
yData.push(item.count);
});
sort(chartData);
initOsChart(xData, yData);
}
}, [chartData]);
const initOsChart = (xData, yData) => {
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(ref.current);
//配置项
const option = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow', // 默认为直线,可选为:'line' | 'shadow'
shadowStyle: {
color: 'rgba(220, 220, 220, 0.2)',
},
},
formatter: function (params) {
return params[0].marker + params[0].name + ' ' + params[0].value + ' 元';
},
},
grid: {
left: '13%',
right: '13%',
},
dataZoom: [
{
type: 'slider',
// startValue: 0,
// endValue: 10,
},
],
xAxis: {
data: xData,
name: '测试数据',
},
yAxis: { name: '金额/元', minInterval: 1 },
series: {
barWidth: xData.length <= 10 ? 40 : xData.length <= 20 ? 25 : 10,
itemStyle: {
normal: {
color: (arg) => {
var colorList = [
'#ea7ccc',
'#9a60b4',
'#fc8452',
'#3ba272',
'#73c0de',
'#ee6666',
'#fac858',
'#91cc75',
'#5470c6',
];
return colorList[(arg.dataIndex / 6).toFixed()];
},
},
},
type: 'bar',
data: yData,
encode: { x: '_id', y: 'count' },
datasetIndex: 1,
label: {
normal: {
show: true,
position: 'top',
},
},
},
};
// 使用刚指定的配置项和数据显示图表
myChart.setOption(option);
// 响应式布局和自适应大小
window.addEventListener('resize', () => {
myChart.resize({ width: window.innerWidth * (1 / 2) - 120 + 'px' });
});
};
return (
<div>
<div
ref={ref}
style={{ height: '280px', width: window.innerWidth * (1 / 2) - 120 + 'px' }}
id="card"
></div>
</div>
);
};
export default evaChart;
其中,不在使用100%为echarts的父元素设定宽度,而是直接获取屏幕的分辨率,根据自己需要的比率计算出宽度来赋予。当然,在reszie()中也得将宽度这样赋予,这样就能保证echarts图的完美自适应。