Echarts獲取縱坐標刻度間距的算法思考


概述

近期面試問到了一些原理性的東西,所以打算把這個也做一個整理,記錄下來,供以后開發時參考,相信對其他人也有用。

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.以后在其它地方進行分段的時候,可以參考這里的分段代碼了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM