比例尺是 D3 中很重要的一個概念,直接用數值的大小來表明像素不是一種好方法數組
1、爲何須要比例尺app
製做一個柱形圖,會有一個數組:var dataset = [ 250 , 210 , 170 , 130 , 90 ];dom
繪圖時,直接使用 250 給矩形的寬度賦值,即矩形的寬度就是 250 個像素。此方式很是具備侷限性,若是數值過大或太小,例如:svg
var dataset_1 = [ 2.5 , 2.1 , 1.7 , 1.3 , 0.9 ];
var dataset_2 = [ 2500, 2100, 1700, 1300, 900 ];函數
對以上兩個數組,毫不可能用 2.5 個像素來表明矩形的寬度,那樣根本看不見;也不可能用 2500 個像素來表明矩形的寬度,由於畫布沒有那麼長。spa
因而,咱們須要一種計算關係,可以:將某一區域的值映射到另外一區域,其大小關係不變。這就是比例尺(Scale)。code
2、有哪些比例尺blog
比例尺,很像數學中的函數。例如,對於一個一元二次函數,有 x 和 y 兩個未知數,當 x 的值肯定時,y 的值也就肯定了。ip
在數學中,x 的範圍被稱爲定義域,y 的範圍被稱爲值域。utf-8
D3 中的比例尺,也有定義域和值域,分別被稱爲 domain 和 range。開發者須要指定 domain 和 range 的範圍,如此便可獲得一個計算關係。
D3 提供了多種比例尺,下面介紹最經常使用的兩種。
一、線性比例尺
線性比例尺,能將一個連續的區間,映射到另外一區間。要解決柱形圖寬度的問題,就須要線性比例尺。假設有如下數組:var dataset = [1.2, 2.3, 0.9, 1.5, 3.3];
現有要求以下:
將 dataset 中最小的值,映射成 0;將最大的值,映射成 300。
var min = d3.min(dataset); var max = d3.max(dataset); var linear = d3.scale.linear() .domain([min, max]) .range([0, 300]); linear(0.9); //返回 0 linear(2.3); //返回 175 linear(3.3); //返回 300
其中,d3.scale.linear() 返回一個線性比例尺。domain() 和 range() 分別設定比例尺的定義域和值域。在這裏還用到了兩個函數,它們常常與比例尺一塊兒出現:
這兩個函數可以求數組的最大值和最小值,是 D3 提供的。按照以上代碼,
比例尺的定義域 domain 爲:[0.9, 3.3]
比例尺的值域 range 爲:[0, 300]
所以,當輸入 0.9 時,返回 0;當輸入 3.3 時,返回 300。當輸入 2.3 時呢?返回 175,這是按照線性函數的規則計算的。
有一點請你們記住:
d3.scale.linear() 的返回值,是能夠當作函數來使用的。所以,纔有這樣的用法:linear(0.9)。
二、序數比例尺
有時候,定義域和值域不必定是連續的。例如,有兩個數組:
var index = [0, 1, 2, 3, 4];
var color = ["red", "blue", "green", "yellow", "black"];
咱們但願 0 對應顏色 red,1 對應 blue,依次類推。
可是,這些值都是離散的,線性比例尺不適合,須要用到序數比例尺。
var ordinal = d3.scale.ordinal() .domain(index) .range(color); ordinal(0); //返回 red ordinal(2); //返回 green ordinal(4); //返回 black
3、給柱形圖添加比例尺
<body> <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> <script> var width = 300; //畫布的寬度 var height = 300; //畫布的高度 var svg = d3.select("body") //選擇文檔中的body元素 .append("svg") //添加一個svg元素 .attr("width", width) //設定寬度 .attr("height", height); //設定高度 var dataset = [ 2.5 , 2.1 , 1.7 , 1.3 , 0.9 ]; var linear = d3.scale.linear() .domain([0, d3.max(dataset)]) .range([0, 250]); var rectHeight = 25; //每一個矩形所佔的像素高度(包括空白) svg.selectAll("rect") .data(dataset) .enter() .append("rect") .attr("x",20) .attr("y",function(d,i){ return i * rectHeight; }) .attr("width",function(d){ return linear(d);//在這裏用比例尺 }) .attr("height",rectHeight-2) .attr("fill","steelblue"); </script> </body>