y軸數據變換利器——yaxis-transformer

倉庫

yaxis-transformer已經發布到npm, 點擊查看源碼, 歡迎star。git

前言

前不久筆者分享過y軸數據處理方案的基本思路,當時需求比較緊張,苦於沒有時間去整理代碼。如今恰好空閒下來,回頭看看以前的代碼,發現存在幾個問題:業務侵入性太強, 定製化能力太弱和方案設計不夠合理。因此決定這一次趁熱打鐵,對整個方案從新設計,將y軸的數據變換能力抽成底層功能庫,而且提供足夠強的定製化能力。這樣的好處是能夠移出以前的業務邏輯代碼,避免庫邏輯混亂和過於累贅,將業務邏輯的處理轉交給使用者。github

分析

整個方案大體能夠分四個步驟:npm

  • 處理最小值minData,找出規整間距interval,計算最大值maxData;
  • 找出須要格式化的單位unit;
  • 計算建議小數位數adviseDecimal;
  • 生成最終結果transformResult。

1. 數據處理

如下例子使用的count=3,即總共生成四個數據。數組

  • 首先是處理最小值minData, 首先根據原始的interval獲得規整的基準值baseInterval, baseInterval的做用是找出minData須要處理的部分remainPart,例如minData爲1542,baseInterval爲200,那麼可知remainPart爲542,接着再對remainPart進行查找基準值的操做,假定結果爲500,那麼處理以後的minData就爲1000 + 500 = 1500。bash

  • 找出規整間距interval,根據前面處理的minData和原始的maxData,再根據基準值生成的策略獲得新的間距,如minData=1000, maxData=6100, interval=1700, 生成的基準值數組爲1000, 2000, 5000, 生成的策略以下:post

defaultBaseGenStrategy = (originInterval: number) =>  {
        let base = AxisHelper.genPowNum(originInterval)
        return [10 * base, 5 * base, 2 * base, base]
  }
複製代碼

那對於間距來講,須要取出第一個比它大的數,因此可算出interval就是2000。ui

  • 最大值就等於 minData + count * interval

2. 找出格式化單位

一般會預設一組用於格式化的單位,例如:[{range: 10000, unit: "萬"}, {range: 100000000, unit: "億"}]
若是超過range,則使用相對應的unit。
特別地,對於百分數的狀況使用的單位以下:{range:0.01, unit:"%"}
對於單位的格式化,主要在於使用哪一個值用來作單位的查找,所以我提供了maxData和minData兩種選擇。spa

3. 計算建議小數位數

因此建議的小數位數,我這裏的定義是指在單位unit的格式化下,仍然能完整顯示出全部有效的小數位數。例如一組數據[100, 10100, 20100],單位是{range: 10000, unit: "萬"}, 那麼建議的小數位數就是2,這樣格式化出來的數據就是[0.01萬, 1.01萬,2.01萬]。
關鍵的地方在於找出最小值min和參考值reference,最小值是爲了保證有效的數據輸出,而reference則是min用於參考的值。如上,min爲100,reference爲20100, 那麼單位就爲萬,小數位數爲2。設計

4. 生成結果

當完成上述步驟,結果就已經呼之欲出。最後就是生成相應的數組,格式大體以下:code

{
   data: [0, 10000, 20000, 30000],
   dataUnit: ['0.00', '1.00萬', '2.00萬', '3.00萬'], 
   adviseDecimal: 1 
 }
複製代碼

使用

const yaxisTransformer = new YaxisTransformer([1542, 6100])
    let transformResult  = yaxisTransformer
     .withCount(3)
     .withMinToZero(false)
     .withUnitFollowMax(false)
     .withFormatRuler((data, decimal) => {
         return data.toFixed(decimal)
     })
     .withUnitSet([{range:10000, unit:"萬"}])
     .transform()

複製代碼

經過建造者模式,增長靈活的定製化配置,目前有的配置以下:

  • withCount 設置生成間距的數量,四個數的數組count即爲3
  • withUnitSet 設置格式化單位,默認爲 [{range: 10000, unit: "萬"}, {range: 100000000, unit: "億"}]
  • withPercentUnit 使用百分比作格式化
  • withMinMaxData 設置最大值最小值
  • withBaseGenStrategy 設置基準值生成策略,默認爲
defaultBaseGenStrategy = (originInterval: number) =>  {
        let base = AxisHelper.genPowNum(originInterval)
        return [10 * base, 5 * base, 2 * base, base]
  }
複製代碼
  • withFormatRuler 設置格式化小數位數的規則,默認爲 number.toFixed(decimal)

  • withForceDecimal 強制設置小數位數

  • withKeepZeroUnit 是否保留0的單位

  • withKeepUnitSame 數組裏的每一個值單位是否保持單位一致

  • withUnitFollowMax 格式化的單位否是參考最大值

  • withMinToZero 最小值< 間距時,是否取0, 如min=100,interval爲1000,是否令min = 0

  • withKeepZeroDecimal 是否保持0的小數位數,如0.00是否格式化爲0

提供了大量能想到用以配置的屬性。

總結

對於底層通用庫,亟需遵照開閉原則,對擴展開放,對修改封閉,對於npm的庫,自然就是封閉的,因此開放就須要提供足夠的定製化能力,減小本身業務邏輯的侵入。

致謝

相關文章
相關標籤/搜索