这几天收到了一个新的需求,就是老大说我们y轴的数据差距太大,导致页面很丑,让我优化一下,下面上图:
有没有感觉巨丑,第一个百分比太大了,导致后面正常的百分比几乎都在下面了。于是我就翻看官网找到了第一个解决方案
将yAxis的type设置为log,这个方式可以很好的解决这个问题,但是有一个前提就是你的数据不能为负数,如果为负数,则数据渲染会出错。那我们的y轴数据中假设就有负数咋办?那我们就用第二种方式解决。
1、设置y轴间隔(这个间隔是初始间隔,你可以根据业务需求修改)
注意:每个echarts对象的dataInterval可能都不一样,建议一个echarts对象一个dataInterval
dataInterval: [0,10, 30, 50, 100,150,200,10000]
2、根据原始数据修改上面的y轴间隔
因为你的y轴数据可能不在上面设置的初始化间隔内,所以可以稍微修改一下y轴间隔数据
// 求得要处理的y轴数据的最大值和最小值
const dataInterval = this.parseInterval([...actualAmountWithSamePeriodRateList,...amountRateList])
getPNum(num) {
num = num.toString();
let firstNumber = num.substr(0,1);
let endNumber = num.substr(1)
return `${parseInt(firstNumber)+1}${'0'.repeat(endNumber.length)}`
},
parseIntervalNum(num) {
// 记录前缀,主要为负数提供服务
let prefix = '';
if(num < 0) {
prefix = '-'
}
// 将num转为正整数
num = Math.abs(parseInt(num))
let p_num = '';
switch(num.toString().length) {
case 1: p_num = 10;break;
case 2: p_num = 100;break;
case 3: p_num = 1000;break;
case 4: p_num = this.getPNum(num);break;
default: p_num = this.getPNum(num);break;
}
let finalNum = `${prefix}${p_num}`
return parseInt(finalNum)
},
parseInterval(initData) {
const dataInterval = [...this.dataInterval]
// 完善y轴的间隔
let max_i = Math.max(...dataInterval);
let min_i = Math.min(...dataInterval);
let maxData = Math.max(...initData);
let minData = Math.min(...initData);
if(maxData > max_i) {
dataInterval.push(this.parseIntervalNum(maxData))
}
if(minData < min_i) {
dataInterval.unshift(this.parseIntervalNum(minData))
}
return dataInterval
},
3、将原始数据做一些转换
let diff = Math.max(...actualAmountWithSamePeriodRateList,...amountRateList) - Math.min(...actualAmountWithSamePeriodRateList,...amountRateList)
let actualAmountWithSamePeriodRateList2 = this.echartsDataParse(actualAmountWithSamePeriodRateList,dataInterval);
let amountRateList2 = this.echartsDataParse(amountRateList,dataInterval);
echartsDataParse(data,dataInterval) {
// 定义数据间隔
let echartsData = []
data.forEach((item, index) => {
// 在数据间隔中查找小于当前项的最大值
const min_v = Math.max(...dataInterval.filter(v => v <= item));
// 在数据间隔中查询大于当前项的最小值
const max_v = Math.min(...dataInterval.filter(v => v > item));
// 寻找min_v所在下标
const index_v = dataInterval.findIndex(v => v === min_v);
// 计算该项在y轴上应该展示的位置
let y_value = ((item - min_v) / (max_v - min_v)) * 10 + index_v * 10;
// 这里处理一下极限值
y_value = y_value > 75 ? 74.99 : y_value
echartsData.push(y_value)
})
return echartsData;
},
4、把转换后的数据挂到series上面
series: [
{
name: '增长率1',
type: 'line',
data: diff > 200 ? amountRateList2 : amountRateList
},
{
name: '增长率2',
type: 'line',
data: diff > 200 ? actualAmountWithSamePeriodRateList2 : actualAmountWithSamePeriodRateList
}
],
5、修改yAxis的axisLabel的formatter
yAxis: [
{
type: 'value',
name: '百分比',
axisLabel: {
// formatter: '{value}%'
formatter: (v,i) => {
if(diff > 200) {
return this.axisLabelFormat(v,i,'%',dataInterval)
}
return `${v}%`
}
},
nameTextStyle: {
fontSize: '16', //字体大小
fontWeight: 700 //字体加粗
},
}
]
axisLabelFormat(v,i,suffix="",dataInterval) {
dataInterval.forEach((item,index) => {
if(i == index) v = item+suffix
})
return v;
/*
if (i === 0) {
v = '0';
}
if (i === 1) {
v = '10';
}
if (i === 2) {
v = '30';
}
if (i === 3) {
v = '50';
}
if (i === 4) {
v = '200';
}
if (i === 5) {
v = '1000';
}
if (i === 6) {
v = '5000';
}
if (i === 7) {
v = '12000';
}
return v;
*/
},
6、修改tooltip
由于我们挂载到series的值是转换后的值,所以我们在这里的提示要改为原来的值
tooltip: {
show: true,
trigger: 'item',
formatter: (params) => {
if(params.componentSubType === 'line') {
if(params.seriesName === '增长率2') {
return `${params.seriesName}
${params.marker}${params.name}${actualAmountWithSamePeriodRateList[params.dataIndex]}%`
}else if(params.seriesName === '增长率1') {
return `${params.seriesName}
${params.marker}${params.name}${amountRateList[params.dataIndex]}%`
}
}else if(params.componentSubType === 'bar') {
return `${params.seriesName}
${params.marker}${params.name}${this.toInt(params.value)}`
}
}
},
至此这个问题就解决啦,下面上解决后的图
注意:这里需要优化一下,如果y轴的值相差在200以内,我们就不需要进行数据处理,只有大于200甚至更大的时候才进行处理,否则会造成数据渲染不正确。