笔者最近在作图表需求,遇到一个这样的问题,图表的y轴数据处理得不够好看,以下:javascript
图表的数据为1005,1988,2500,3902,5530,很显然这个处理数据的结果不尽人意。java
既然有这个问题,那么就须要一个新的处理方案,平时咱们在使用Excel等工具制做的折线图,会发现上面的数据实际上是处理过的了,以下: 工具
对于笔者而言,需求不只包含数据的规整,还有小数位数的格式化,其中涉及到单位的转换,如初始值给了10345,21200,29001,y轴格式化为1.0万,2.0万,3.0万,那么须要对小数位数作处理,使得最后结果为1万,2万,3万。因此对于笔者而言,找出间隔以后,还须要对最终结果的小数位数作去0操做。ui
首先,须要找出数据集的最小值min,最大值max,这里笔者给出的数据为min = 47769543,max = 54961473,最多须要保留的小数位数decimal=1。还包含如下须要用到的方法:this
方法名 | 做用 |
---|---|
formatDataByRanges | 对数据进行单位转换处理,如47769534作“万”处理则为 4776.9534 |
export function genIntervalList(originInterval: number) {
let base = genPowNum(originInterval)
return [10 * base, 5 * base, 2 * base, base]
}
// 获取数字的十的幂次方的位数
// 如 90 则为 1
// 如 0.01则为 -2
function getPowBit(number) {
return Math.floor(Math.log10(data))
}
/** * 生成十的幂次方 * @param data */
export function genPowNum(data: number) {
let bit = getPowBit(data)
return Math.pow(10, bit)
}
复制代码
接着从第二个数开始遍历1000 500 200 100, 当找到大于originInterval的数时则中止,获取当前点的上一个数为咱们所需的interval,如179.798 > 100, 那么interval就为200。而后经过interval对min作处理,固然这里的min也通过处理为4776.9543,处理过程以下:spa
function handleMin(min, interval) {
if(min < interval) {
return 0
} else {
let baseNum = genPowNum(interval) * 10
// 去掉最小值不须要比较的位数
// 如min为4776.9543 interval为200 那么formatMin = 4000
// 如min为0.073 interval为0.005 那么formatMin = 0.07
let formatMin = Math.floor(min / baseNum) * baseNum
let minRange = min - formatMin
// 找出适合的interval 这里为500
// 因此最后的min = 4000 + 500 = 4500
return formatMin + this.findMinInterval(minRange, interval)
}
}
function findMinInterval(minRange: number, interval: number) {
let factorList = genIntervalList(interval)
for (let i = 1; i < factorList.length; i++) {
if (minRange >= factorList[i]) {
return factorList[i]
}
}
return 0
}
复制代码
通过上述的处理,可得最小值为4500code
找间距
因为通过步骤1肯定了min,min已经改变了,因此range须要从新计算,interval也须要从新计算。计算方式参考步骤1的找间距,计算可得interval为500。orm
最终计算
通过步骤1,2能够获得min和interval,若是此时min< interval,那么须要令min = 0,而后从新执行步骤2。这样就能够获得最后的min,interval,接着须要计算最后须要保留的小数位数,以下:cdn
function getDecimal(interval, min) {
if(interval < 1) {
return Math.abs(getPowBit(interval))
} else {
// 若是间距的range和max相等 则不须要保留小数位数
// 如interval是1500万 max是4000万 range都为万 不须要保留小数
if(interval.range = max.range) {
return 0
} else {
// 当range不相等的状况 可知min必定大于formatInterval
// 如min为121.1万 interval为2000 这时候对2000作range的处理
// 则可获得最大须要保留的位数
return Math.abs(getPowBit(formatInterval / formatMinData.range))
}
}
}
复制代码
对于这个方案,在于肯定min和interval,对于interval而言,则能够本身灵活定义规整的间距,如520取的是550,而不是1000,这样的好处是可让图表的走势更加明显。blog