5

最近项目组接到了许多对图表有特殊要求的需求,比如今天说的这个呈现光纤的中断时长分布的需求:
光纤的中断大部分落在30分钟之内,但偶尔遇到特殊情况时,会出现中断一两天甚至更长的时间,如果把这些时长分布放在一个刻度均匀的数轴上,势必造成大部分的指标(此处为柱状图)特别短的问题,因此,希望建立一个刻度一开始均匀分布,比如10min、20min,到60min之后立刻升为2hour、1day这样的需求。

一开始拿到这个任务,我的第一反应,是查找Echarts的配置项手册,希望通过在yAxis上做手脚来解决问题。然鹅事情总是没有想象的顺利,echart对y轴对配置只能指定几种type:‘category’、‘value’和‘log’,虽然配置为log对数轴也可以解决较大值对较小值对影响的问题,但当值较小时也无法通过长度区分开,不够完美。

庆幸的是,在echarts的GitHub官网上,pissang大大给出了一个思路:

图片描述

深受启发!为什么一定要依赖Echarts本身给予解决方案呢?完全可以自己构造一个新的分布呀!

不多说,开始码:

第一步:利用yAixs.axisLabel.formatter伪造一个不均匀坐标轴

先给大家看看具体的代码:

//利用formatter将y轴上本来为70(min),80(min)的点强制改为2hour和1day
formatter:function(value) { 
    let item='';
    if(value==70){
        item='2hour'            
    }else if(value===80){
        item='1Day'
    }else{
        item=value+' min'
    }
    return item
} 

第二步:将数据映射到一个特定的分布

这句话的意思,其实就是自己构造一个函数,将原始数据里较大的数值转换成一个小数值

我是这样做的:

//模拟数据,其中的200、150是应该落在2hour和1day之间,所以映射后的数据应该落在70min到80min之间
let data = [10, 15, 4, 20, 200, 150, 19,70,1441];
function formatData(arr){    //自己构造一个用来映射data到均匀数轴上的方法
    for(let i=0;i<arr.length;i++){
        if(arr[i]>60&&arr[i]<=120){
            let percent1=(arr[i]-60)/120;
            arr[i]=percent1*10+60;
        }else if(arr[i]>120&&arr[i]<1440){
            let percent2 =(arr[i]-120)/1440;
            console.log(percent2);
            arr[i]=percent2*10+70;
        }
    }
    return arr;
}

上面这个formatData,其实就是对data数组里超过60的数据进行改造,如果这个数据超过了60min且小于120min(2hour),就按照这个数据在60到120段应该有的比例,映射到60到70段里,而超过2hour且小于1day的数据,则同样按这个方法,计算映射到70到80段里

这样一来,任务已经基本完成啦!

第三步:将数据反映射为原来的值

但是现在在图表里,我们拿到的是映射后的数据,如果此时的tooltip是开放的,那么用户在tooltip里读到的数据就不是原来的200min,150min这种的了,而变成了一个70min到80min之间的较小数据。怎么办?只能在每个需要展示数据的地方,严防死守,将这几条特殊的数据反计算回去咯!

tooltip:{
    formatter:function(params) {  //由于在tooltip里需要展示原始的数据,所以要把映射后的数据反计算回去
        let str=params.name+':'+params.value;
        if(params.value>=60&&params.value<70){
            let percent = (params.value-60)/10
            let value = Math.round(percent*120+60);//注意此处的percent已经是个浮点数了,所以得到value之前要用四舍五入取整才行
            str=params.name+' : '+value;
        }else if(params.value>70&&params.value<80){
            let percent = (params.value-70)/10;
            let value =Math.round(percent*1440+120);
            str=params.name+' : '+value;
        }
        return '<div style="width:70px;height:50px;display:flex;align-items:center">\
            <span style="background-color:#D53A35;width:15px;height:15px;display:inline-block;border-radius:50%"></span>\
            <span>'+str+'</span>\
        </div>'
    }
}

嗯,现在就可以了,接下来上一个效果图炫耀一下:
图片描述

一切看上去都是那么的完美,其实这种方法当然还是瑕疵的,你能看出来吗:)


CatherineYF
167 声望3 粉丝