Echarts实现折线图Y轴不等距百分比(最终解决方案-上集)
- 出现背景
- 解决思路
- 总结
- 附加
出现背景
最近公司有一个需求,主要是想展示近7日产品的一个良品率(百分率制)。但是呢,基本上每天这个百分比率在90%~100%之间,很少有低于90%的。我就根据这个需求,很快就做出折线图表,图表右侧的Y轴是从0%-100%,并按20%间隔。
给到产品后,TA说线上的数据基本上都是90%-100%,你这样的话就看不出太大的折线趋势,折线的起伏不是很明显,下面空白了一大片,着眼一看,确实不利于观测。
后来,TA说因为数据比较固定,那么是否可以设置一个最低值呢?比如,在Y轴最低处设置一个60%,那整体不是就拉伸开了吗。后来我就尝试了一下,如下图所示:
刚开始以为就这么简单搞定,当天测试工程师测试的时候,又发现一个问题。如果中间某一天没有生产,那么就没有数据,没有数据当时处理为0。不过图表它就不这样认为了,我偏要捣乱一下。当中间某一天没数据时,如下图所示:
我勒个去,这是什么鬼,29日那天没数据默认为0,结果就飞到下面去了,显然不符合需求。那么就设置一个最低值为0,第二隔为60%,这样子总可以了嘛。来吧,如下图所示:
到这里我觉得应该搞定了,给产品看了过后,TA觉得还行,那就这样吧。
没过多久,突然出现某一天良率为80%,和Y轴的刻度对不上,然后检查后才发现全部的都没对应上Y轴。如下图所示:
原因:虽然我们Y轴设置了不等距显示,但是实际上Y轴还是按照原来0-100%,来均匀分布,并没有实现不等距显示效果,想到这个问题很头疼。
当天查了很多资料,都没有找到相应的解决办法。晚上回家也很想了很久,第二天上班突然灵机一动,可以根据Y轴比例和当前良率的值来设定它的对应位置,虽然麻烦点。
****以上就是我在开发过程中遇到的一个Echart折线图不等距百分比率问题,下面会跟大家讲一下我的思路和相关算法。
解决思路
根据上面出现的问题,下面我们就开始解决。
在开始之前先给大家看一个刻度对比图:
所以根据这个比值我们得到一个简单比例公式,即:
当百分比为0~60%时,对应真实值为20,比例为1/3
当百分比为60~100%时,对应真实值为80,比例为2
所以咱们要做的就是,把坐标点的位置通过这个比例来进行分配,算法如下:
//折线图坐标点算法
function initPointData(pointData) {
var baseNum = 20; //基础数 0~60%那一段的真实值
var returnPosition = 0; //初始化返回的值
if (pointData <= 60) { //判断当前真实百分比是否<=60%
returnPosition = pointData / 3;
// 通过比例来算出它的位置,例如:30% ,30/3 =10,
它就在真实值10的位置,对应折线30%,其他小于60的如此
} else if (pointData > 60 && pointData <= 100) {
returnPosition = (pointData % 60) * 2 + baseNum
// 重点:如果高于60%,那么就对当前这个
百分比取60%的余,再乘以它的比例2,再加上基础值20,那么就是高于60%以上的位置。
例如: 75%,75%60 =15,15*2=30,30+20=50,那么75%其实是对应Y轴真实值50,其他也如此
} else {
returnPosition = 0;
}
return returnPosition
}
现在大家应该都知道这个算法,接下来咱们来看看其他部分怎么实现:
1、定义option中的yAxis
yAxis: [{
type: 'value',
name: '良率',
splitLine: {
show: true,
},
position: 'right',
min: 0, //一定要设置最小刻度
max: 100, //一定要设置最大刻度
minInterval: 20, //这个可自己设置刻度间隔
axisLabel: {
formatter: function (value, index) { //Y轴的自定义刻度值,对应上图
if (index == 0) {
value = 0
} else if (index == 1) {
value = 60
} else if (index == 2) {
value = 70
} else if (index == 3) {
value = 80
} else if (index == 4) {
value = 90
} else if (index == 5) {
value = 100
}
return value+'%';
}
},
}],
2、设置option中的series参数(动态生成)
var oneData = [89.25, 92.94, 70.001, 97.55, 97, 92.74, 94];
var allData = [78, 86.55, 80.56, 86, 89.02, 92, 97.56];
myChart1.setOption({
xAxis: [{
data: ['26日', '27日', '28日', '29日', '1日', '2日', '3日'],
}],
series: initItem(oneData, allData)
});
//初始化折线图
function initItem(oneData, allData) {
var dataItem = [{
name: '一次良率',
data: getData(oneData)
}, {
name: '综合良率',
data: getData(allData)
}]
return dataItem;
}
function getData(temp) {
var jsonString = [];
for (var i = 0; i < temp.length; i++) {
var json = {};
json.name = temp[i] > 100 ? 0 : temp[i];
json.value = initPointData(temp[i]);
jsonString.push(json);
}
return jsonString;
}
//折线图坐标点算法
function initPointData(pointData) {
var baseNum = 20;
var returnPosition = 0;
if (pointData <= 60) {
returnPosition = pointData / 3;
} else if (pointData > 60 && pointData <= 100) {
returnPosition = (pointData % 60) * 2 + baseNum
} else {
returnPosition = 0;
}
return returnPosition
}
以上代码就是生成每个折线点的方法,代码其实很简单,大家可以参考~
其他属性就没全部贴出,大家看以上部分代码即可。
最终效果如下:
3、弹窗显示tooltip属性设置
这个tooltip属性是鼠标放上去显示的详细数值,这个也需要自定义,不然不能显示。
代码如下所示:
tooltip: {
trigger: 'axis',
formatter: function (params) {
var result = ''
var axisName = ''
params.forEach(function (item) {
axisName = item.axisValue
var itemValue = item.marker + item.seriesName + ": " + item.data.name + "%</br>"
result += itemValue
})
var allResult = axisName + "</br>" + result
return allResult
}
},
需要注意的是,这个的itemValue取值不能取真实的值,只能取之前的折线图坐标值,也就是位置。
总结
以上就是关于不等距的解决方法,如果有更好的方法也可以互相交流。初次写博客,如有不足之处敬请各位指出,有什么好的建议也可提出,共同学习共同进步!
附加
一下节,我会在此问题基础上解决另外一个刻度问题,让Y轴最低刻度随数值动态变化。比如,取当前数组最小的值,向下取余整数,就为Y轴刻度的最低值。
来自一个被编程耽搁的健身教练编写于公元2020年3月25日