筆者最近在作圖表需求,遇到一個這樣的問題,圖表的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