D3中有個重要的概念就是比例尺。比例尺就是把一組輸入域映射到輸出域的函數。映射就是兩個數據集之間元素相互對應的關係。好比輸入是1,輸出是100,輸入是5,輸出是10000,那麼這其中的映射關係就是你所定義的比例尺。javascript
D3中有各類比例尺函數,有連續性的,有非連續性的,本文對於經常使用比例尺進行一一介紹。java
使用d3.scaleLinear()
創造一個線性比例尺,而domain()
是輸入域,range()
是輸出域,至關於將domain
中的數據集映射到range
的數據集中。git
let scale = d3.scaleLinear().domain([1,5]).range([0,100])
映射關係:github
接下來,咱們來研究這個比例尺的輸入和輸出。segmentfault
scale(1) // 輸出:0 scale(4) // 輸出:75 scale(5) // 輸出:100
剛纔的輸入都是使用了domain
區域裏的數據,那麼使用區域外的數據會得出什麼結果呢?數組
scale(-1) // 輸出:-50 scale(10) // 輸出:225
因此這只是定義了一個映射規則,映射的輸入值並不侷限於domain()
中的輸入域。dom
d3.scaleBand()
並非一個連續性的比例尺,domain()
中使用一個數組,不過range()
須要是一個連續域。函數
let scale = d3.scaleBand().domain([1,2,3,4]).range([0,100])
映射關係:flex
看一下輸入與輸出:ui
scale(1) // 輸出:0 scale(2) // 輸出:25 scale(4) // 輸出:75
當輸入不是domain()
中的數據集時:
scale(0) // 輸出:undefined scale(10) // 輸出:undefined
因而可知,d3.scaleBand()
只針對domain()
中的數據集映射相應的值。
d3.scaleOrdinal()
的輸入域和輸出域都使用離散的數據。
let scale = d3.scaleOrdinal().domain(['jack', 'rose', 'john']).range([10, 20, 30])
映射關係:
輸入與輸出:
scale('jack') // 輸出:10 scale('rose') // 輸出:20 scale('john') // 輸出:30
當輸入不是domain()
中的數據集時:
scale('tom') // 輸出:10 scale('trump') // 輸出:20
輸入不相關的數據依然能夠輸出值。因此在使用時,要注意輸入數據的正確性。
咱們從上面的映射關係中能夠看出,domain()
和range()
的數據是一一對應的,若是兩邊的值不同呢?下面兩張圖說明這個問題:
domain()
的值按照順序循環依次對應range()
的值。
d3.scaleQuantize()
也屬於連續性比例尺。定義域是連續的,而輸出域是離散的。
let scale = d3.scaleQuantize().domain([0, 10]).range(['small', 'medium', 'long'])
映射關係:
輸入與輸出:
scale(1) // 輸出:small scale(5.5) // 輸出:medium scale(8) // 輸出:long
而對於domain()
域外的狀況:
scale(-10) // 輸出:small scale(10) // 輸出:long
大概就是對於domain()
域的兩側的延展。
d3.scaleTime()
相似於d3.scaleLinear()
線性比例尺,只不過輸入域變成了一個時間軸。
let scale = d3.scaleTime() .domain([new Date(2017, 0, 1, 0), new Date(2017, 0, 1, 2)]) .range([0,100])
輸入與輸出:
scale(new Date(2017, 0, 1, 0)) // 輸出:0 scale(new Date(2017, 0, 1, 1)) // 輸出:50
時間比例尺較多用在根據時間順序變化的數據上。另外有一個d3.scaleUtc()
是依據世界標準時間(UTC)來計算的。
D3提供了一些顏色比例尺,10就是10種顏色,20就是20種:
d3.schemeCategory10
d3.schemeCategory20
d3.schemeCategory20b
d3.schemeCategory20c
// 定義一個序數顏色比例尺 let color = d3.scaleOrdinal(d3.schemeCategory10)
另外有一些函數比例尺的功能,從名稱上就可見一斑。
d3.scaleIdentity() // 恆等比例尺 d3.scaleSqrt() // 乘方比例尺 d3.scalePow() // 相似scaleSqrt的乘方比例尺 d3.scaleLog() // 對數比例尺 d3.scaleQuantile() // 分位數比例尺
invert()
與invertExtent()
方法上述的各類使用比例尺的例子都至關於一個正序的過程,從domain
的數據集映射到range
數據集中,那麼有沒有逆序的過程呢?D3中提供了invert()
以及invertExtent()
方法能夠實現這個過程。
let scale = d3.scaleLinear().domain([1,5]).range([0,100]) scale.invert(50) // 輸出:3 let scale2 = d3.scaleQuantize().domain([0,10]).range(['small', 'big']) scale2.invertExtent('small') // 輸出:[0,5]
不過,值得注意的是,這兩種方法只針對連續性比例尺有效,即domain()
域爲連續性數據集的比例尺。那麼非連續性的比例尺就沒有invert()
方法了嗎?
到此,對於D3V4版本中的常見比例尺的映射關係都進行了介紹,而各個比例尺還提供了許多其餘功能,好比在繪製座標軸中用到的ticks()
,tickFormat()
等功能,具體API能夠參見此處。關於第8點最後提出的問題,請聽下回分解。