echarts 折线图y轴数据相差巨大的解决方案

这几天收到了一个新的需求,就是老大说我们y轴的数据差距太大,导致页面很丑,让我优化一下,下面上图:

echarts 折线图y轴数据相差巨大的解决方案_第1张图片

有没有感觉巨丑,第一个百分比太大了,导致后面正常的百分比几乎都在下面了。于是我就翻看官网找到了第一个解决方案

解决方案一:

echarts 折线图y轴数据相差巨大的解决方案_第2张图片

将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)}` } } },

至此这个问题就解决啦,下面上解决后的图

echarts 折线图y轴数据相差巨大的解决方案_第3张图片

注意:这里需要优化一下,如果y轴的值相差在200以内,我们就不需要进行数据处理,只有大于200甚至更大的时候才进行处理,否则会造成数据渲染不正确。

你可能感兴趣的:(vue,echarts,echarts,前端,javascript)