D3.js比例尺 序數比例尺(v3版本)

溢楊年華發表於2019-05-07

上一章介紹了閾值比例尺:https://www.cnblogs.com/littleSpill/p/10825038.html。到目前所有的定量比例尺已經介紹完了。

現在給大家介紹一下序數比例尺

定量比例尺的定義域都是連續的,值域有連續的也有離散的。序數比例尺(Ordinal Scale)的定義域和值域都是離散的。
 
現實中會有這樣的需求,通過輸入一些離散的值(如名稱、序號、ID等),要得到另一些離散的值(如顏色等),這種時候就要考慮序數比例尺了。
序數比例尺的方法有:
 
d3.scaleBand.ordinal()
//構建一個序數比例尺
 
ordinal(x)
//輸入定義域內一個離散值,返回值域內一個離散值。
 
ordinal.domain([values])
//設定或獲取定義域
 
ordinam.range([values])
//設定或獲取值域
 
ordinal.rangePoints(interval[,padding])
//代替range()設定的值域。接受一個連續的區間,然後根據定義域中離散值的數量將其分段,分段值即作為值域的離散值。
 
ordinal.rangeRoundPoints(interval,[,padding])
//和rangePoints()一樣,但是結果會取整數。
 
ordinal.rangeBands(interval[,padding[,outerPadding]])
//代替range()設定值域。與rangePoints()一樣,也是接收一個連續的區間,然後根據定義域中離散值得數量將其分段,但是其分段方法是不同的。
 
ordinal.rangeRoundBands(interval[,padding,outerPadding])
//和rangeBands()一樣,但是會將結果取整。
 
ordinal.rangBand()
//返回使用rangeBands()設定後每一段的寬度、
 
ordinal.rangeExtend()
//返回一個陣列,陣列裡存有值域的最大值和最小值
 
首先舉個例子,定義一個序數比例尺,定義域設定為[1,2,3,4,5]五個離散值,值域設定為[10,20,30,40,50]五個離散值。看程式碼:
 
 1 var ordinal = d3.scale.ordinal()
 2                         .domain([1,2,3,4,5])
 3                         .range([10,20,30,40,50])
 4 
 5         console.log(ordinal(1))         //輸出10
 6 
 7         console.log(ordinal(3))         //輸出30
 8 
 9         console.log(ordinal(5))         //輸出50
10         
11         console.log(ordinal(8))         //輸出10

 

由此可見,1對應10,3對應30,5對應50,與定義域和值域排列次序一致。但是最後一行輸入值為8,不在定義域內,輸出值為10.先不管其輸出值有沒有道理,總之不要輸入超過定義域的值。
 
但是,如果一個一個地設定值域的值,使其對應到定義域上,比較麻煩。D3提供了rangePoints()rangRoundPoints()用於解決此問題:只要接收一個連續的區間,即可自動計算出相應的離散值。這兩個方法都有兩個引數:intervalpaddinginterval是區間,padding是邊界部分留下的空白。可省略,預設為0。意義如圖:
 
 
如上圖,rnage.interval就是rangePoints()的第一個引數interval的值,是一個範圍,如[0,100]。padding是第二個引數:step是根據定義域的數值計算得到的值。圖中圓圈所代表的點,就是計算得到的離散值。看程式碼:
 
 1  var ordinal2 = d3.scale.ordinal()
 2                         .domain([1,2,3,4,5])
 3                         .rangePoints([0,100])
 4 
 5         console.log(ordinal2.range())        //輸出 [0, 25, 50, 75, 100]
 6 
 7         console.log(ordinal2(1))             //輸出0
 8 
 9         console.log(ordinal2(3))             //輸出50
10         
11         console.log(ordinal2(5))             //輸出100

 

上面程式碼的序數比例尺中,rangePoints()的第一個引數為[0,100],第二個引數省略。對應到上圖的話,則range interval等於[0,100],padding等於0,step等於25.因此,得到了 上面輸出的5個離散值,與定義域的5個值是一一對應的。下面來看看padding有設定值的情況:
 
1    ordinal2.rangePoints([0,100],5)
2         
3         console.log(ordinal2.range())        //輸出[27.77777777777778, 38.888888888888886, 50, 61.11111111111111, 72.22222222222223]

 

這樣設定後,padding等於5,step等於11.111111。則step*padding/2等於27.77777,正是輸出陣列的第一個值。這樣,有時輸出的陣列是無窮小數,如果希望其都是整數,可用rangeRoundPoints()。程式碼 :
 
1    ordinal2.rangeRoundPoints([0,100],5)
2         
3         console.log(ordinal2.range())        //輸出[28, 39, 50, 61, 72]結果被四捨五入取整了

 

D3還提供了rangeBands()rangRouondBands()。與rangePoints()稍有不同的是,其接收三個引數:intervalpaddingouterPadding。各引數的意義如下圖。range interval是範圍。paddingouterPadding分別是內部和邊界的空白的引數,預設為0。rangePoints方框中的rangBand,表示一個區間。而該區間的起點,就是得到的離散值。圖:

 

rangeBand()可返回rangeBand的值。要注意函式名的區別。rangBands()後面有s,用於設定值域。rangeBand()後面沒有s,用於返回圖中rangBand的值,舉個例子:
 
1 var bands = d3.scale.ordinal()
2                     .domain([1,2,3,4,5])
3                     .rangeBands([0,100])
4 
5         console.log(bands.range())          //輸出[0, 20, 40, 60, 80]
6         
7         console.log(bands.rangeBand())      //輸出20

 

這段程式碼中,paddingouterPadding都沒有設定,預設為0.計算可得,rangeBand為20,值域有五個離散的值,分別是每一個rangeBand區域的起點,即[0,20,40,60,80]。下面試一下設定了空白的情況:
 
1 bands.rangeBands([0,100],0.5,0.2)
2 
3         console.log(bands.range())          //輸出[4.081632653061225, 24.489795918367346, 44.89795918367347, 65.3061224489796, 85.71428571428571]
4         
5         console.log(bands.rangeBand())      //輸出10.204081632653061

 

這段程式碼中,padding為0.5,outerPadding為0.2.對應上圖中,step計算的值約等於20,因此左右邊界的空白step*outerPadding約等於4即輸出陣列的第一個值。step*padding約等於10,即每個rangBand之間的空白長度。
 
D3提供了幾個獲取顏色的序數比例尺。製作圖示時,經常需要設定各圖形元素的顏色,每次都要手動設定很麻煩,如果對顏色沒有特殊要求直接使用這些顏色比例尺即可。並且,它們的顏色都經過精心的色彩搭配,相當美觀。顏色比例尺有4個:
 
d3.scale.category10() :
//10種顏色
 
d3.scale.category20() :
//20種顏色
 
d3.scale.category20b() :
//20種顏色
 
d3.scale.category20c() :
//20種顏色
 
這四個都是序數比例尺,輸入離散值後返回也是離散值。例如category10()提供了10種顏色,分別為#1f77b4,#ff7f0e,#2ca02,#d62728,#9467bd,#8c564b,#c377c2,#7f7f7f,#bcbd22,#17becf。看程式碼:
 
1 var color = d3.scale.category10();
2 
3         console.log(color(1))                    //輸出#1f77b4
4         
5         console.log(color("zhangsan"))           //輸出#ff7f0e

 

可以看到,無論輸入值是什麼樣的離散值,該比例尺都按照顏色順序返回:先返回了#1f77b4,再返回#ff7f0e,如果後面還有則繼續返回後面的值。使用這四個比例尺來設定顏色以後會經常見到,比如以下應用:
 
 1      var width = 600;                //svg繪製區域的寬度
 2         var height = 600;               //svg繪製區域的高度
 3         var dataset = d3.range(5);      //返回[0,1,2,3,4,5]
 4        
 5         var color2 = d3.scale.category10();             //定義表示顏色的序數比例尺
 6         
 7         var svg = d3.select("#body")                    //選擇id為body的div
 8                     .append("svg")                      //在<body>中新增<avg>
 9                     .attr("width",width)                //設定<svg>的寬度屬性
10                     .attr("height",height)              //設定<svg>的高度屬性
11                     
12         //繪製圓
13          svg.selectAll("circle")        //選擇所有的圓
14             .data(dataset)              //繫結資料
15             .enter()                    //獲取enter部分
16             .append("circle")           //新增ciecle元素,使其與繫結陣列的長度一致
17             .attr("cx",function(d,i){return 30 + i*80})     //設定圓的x方向的位置
18             .attr("cy",100)             //設定圓的y方向的位置
19             .attr("r",30)               //設定圓的半徑
20             .attr("fill",function(d,i){ //設定圓的顏色
21                 return color2(i)
22             })

 

d3.range()返回一個等差數列,但是此處僅使用其長度,不使用陣列的各項值。以上程式碼繪製了5個圓,再給每個圓設定顏色的時候,使用了color2(i)。color2是顏色比例尺。i是被繫結資料的索引號,被當做color2的引數使用。但是不一定非得用索引號,別的離散值也可以,顏色都會按順序返回。效果圖:
 
 
 
到這一章,比例尺都介紹完了。下一章給大家介紹座標軸的繪製方法、新增座標軸的刻度和各比例尺的座標軸。

 

相關文章