概述
近期面试问到了一些原理性的东西,所以打算把这个也做一个整理,记录下来,供以后开发时参考,相信对其他人也有用。
Echarts获取纵坐标刻度间距的博文请见这里
其实刚开始看Echarts的这段代码我也是一脸懵逼的,但是如果仔细看一下还是觉得挺简单的。
原理
首先,对于纵坐标,我们对它有一个期望的分段值,这个期望的分段值是通过最大数/分段数算出来的,代码如下:
// this.data 是数据
const round = true;
const splitNumber = 4;
const max = this.data.reduce((x,y) => x > y ? x : y);
let val = max / splitNumber;
然后,这个val
就是我们的期望分段值,它可能是500,也可能是333等不规则的数。我们希望能够把它矫正为一个整十整百整千这样的数。怎么做呢?分为两步,第一步是确认到底是整十还是整百还是整千,其实就是看它的0有多少个。第二步是确定最高位上的数是多少,打个比方就是确定500、3000等里面的5、3。
对于第一步很简单,我们对期望的分段值取10的对数,然后 floor 一下,最后还原就得到了:
const exponent = Math.floor(Math.log(val) / Math.LN10);
const exp10 = Math.pow(10, exponent);
比如说,期望分段值是66666,因为他是整万的,所以我们期望得到10000,用上面的代码计算出来果然是10000.
对于第二步,那就更简单了,只需要把66666/10000 = 6.6
进行约分即可,我们可以约成7,那么70000就是我们的实际分段值。所以Echarts用了它自己的一套约分规则:
// 如果传入了 round 参数,则往小的约分
if (round) {
if (f < 1.5) { nf = 1; }
else if (f < 2.5) { nf = 2; }
else if (f < 4) { nf = 3; }
else if (f < 7) { nf = 5; }
else { nf = 10; }
}
else {
// 如果没有传入 round 参数,则往大的约分
if (f < 1) { nf = 1; }
else if (f < 2) { nf = 2; }
else if (f < 3) { nf = 3; }
else if (f < 5) { nf = 5; }
else { nf = 10; }
}
实际上,我们这一步可以向上约分一个最近的整数就行了,比如1.5约分为2,4.6约分为5,7.3约分为8,但是Echarts这里只约到1、2、3、5、10这几个数,把大于5的全部越成了10,可能在实际生产环境中是为了好看吧。
最后把我们第一步和第二步的值相乘就得到了最终的分段值,比如第一步是10000,第二步约成了3,那么最终的分段值为30000。不过最后Echarts处理了一下精度问题:
// Fix 3 * 0.1 === 0.30000000000000004 issue (see IEEE 754).
// 20 is the uppper bound of toFixed.
return exponent >= -20 ? +val.toFixed(exponent < 0 ? -exponent : 0) : val;
总结
1.怎么样?是不是很简单呢?
2.以后在其它地方进行分段的时候,可以参考这里的分段代码了。