D3.js介紹
D3.js 是一個基於數據操作文檔JavaScript庫。D3幫助你給數據帶來活力通過使用HTML、SVG和CSS。D3重視Web標准為你提供現代浏覽器的全部功能,而不是給你一個專有的框架。結合強大的可視化組件和數據驅動方式Dom操作。這裡也可以看到它是用SVG來呈現圖表的,所以使用D3.js是需要一定的SVG基礎的。
如何用D3.js實現柱狀圖?
柱狀圖裡面有坐標軸和柱子。然而我們還需要SVG畫布來畫這些東西。先把大概的畫圖框架搭起來,代碼如下(請注意此時我在body標簽裡添加了D3.js的script標簽。這樣我們後面才能使用D3的方法):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>柱狀圖</title>
<style>
.container {
margin: 30px auto;
width: 600px;
height: 300px;
border: 1px solid #000;
}
</style>
</head>
<body>
<div class="container">
<svg width="100%" height="100%"></svg>
</div>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
<script>
window.onload = function() {
var width = 600, height = 300;
// SVG畫布邊緣與圖表內容的距離
var padding = { top: 50, right: 50, bottom: 50, left: 50 };
// 創建一個分組用來組合要畫的圖表元素
var main = d3.select('.container svg').append('g')
// 給這個分組加上main類
.classed('main')
// 設置該分組的transform屬性
.attr('transform', "translate(" + padding.top + ',' + padding.left + ')');
};
</script>
</body>
</html>
坐標軸的實現
為了把真實的數據與SVG畫布上的坐標軸上的坐標聯系起來,我們需要定義比例尺來描述這樣的對應關系。D3中常用的比例尺有線性比例尺和序數比例尺,它們的區別如圖所示:

從圖上可以看出,線性比例尺的對應關系是連續的,而序數比例尺的對應關系是離散的。分析柱狀圖的展現意義可以得出x軸應該選用序數比例尺,而y軸選用線性比例尺。
// 模擬數據
var dataset = {
x: ["趙","錢","孫","李","周","吳","鄭","王"],
y: [40, 30, 50, 70, 90, 20, 10, 40]
};
// 定義x軸的比例尺(序數比例尺)
var xScale = d3.scale.ordinal()
.domain(dataset.x)
.rangeRoundBands([0, width - padding.left - padding.right],0,0);
// 定義y軸的比例尺(線性比例尺)
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset.y)])
.range([height - padding.top - padding.bottom, 0]);
// 定義x軸和y軸
var xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom');
var yAxis = d3.svg.axis()
.scale(yScale)
.orient('left');
// 添加坐標軸元素
main.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(0,' + (height - padding.bottom - padding.top) + ')')
.call(xAxis);
main.append('g')
.attr('class', 'axis')
.call(yAxis);
我們模擬了一些數據,每個姓氏對應了一個數值(從這裡也可以看出序數比例尺的定義域上的值不一定是連續關系)。d3.scale.ordinal()創建了一個序數比例尺,而ordinal.domain()設置了該比例尺的定義域,ordinal.rangRoundBands()設置了值域。同理,d3.scale.linear()創建了一個線性比例尺,linear.domain()定義定義域,linear.range()定義值域。接著,我們用d3.svg.axis()創建了兩個坐標軸,把比例尺應用到它們上面,並且用axis.orient()設置了坐標軸的刻度尺的方向。最後,添加SVG元素,用call()把定義好的坐標軸與SVG元素聯系起來。通過設置它們的transform屬性來移動元素,使它們看起來像是一個坐標系。
這裡需要注意以下幾點:
1、ordinal.domain的參數是一個表示一系列值的數組,而linear.domain的參數是一個表示范圍的數組。
2、比例尺的本質是一個函數,它接收定義域上的值來得出對應的值域上的值。
應用序數比例尺的坐標軸與線性比例尺的有很大不同,這裡大概說明一下。

rangeRoundBands(interval, padding, outerPadding)中的padding和outerPadding都是可選的,默認為0。如上圖所示的比例尺的代碼是這樣的。
var o = d3.scale.ordinal() .domain([0, 1, 2]) .rangeRoundBands([0, 100], 0.4, 0.1);
domain的參數數組有多少個元素,就會有多少個rangeBand,rangeBand之間的間隔為padding*step(padding取值范圍為0到1),它與rangeBand的關系是均分一個step,比如padding為0.4,則rangeBand的長度為0.6*step。根據上述代碼可得最終坐標軸的長度等於(0.1 + 2 + 0.6 + 0.1) * step,由此算出step的長度,再推出外間距、rangeBand、內間距的長度。而定義域上的取值刻度定位在每個rangeBand的中間。於是得到了示意圖中的坐標軸(紅色標注)。
我們接著來畫柱狀圖,給坐標軸設置一下樣式:
.axis path,
.axis line {
stroke: #000;
fill: none;
}
最終得到的柱狀圖的坐標軸如下圖所示:

柱子的實現
柱子無非就是一個個矩形,在SVG中可以使用rect元素來畫。先選擇到main下所有bar類的元素(此時選擇到的是一個空的集合),把dataset.y綁定到這個集合上,用enter()對比綁定的數組元素個數與集合中的SVG元素個數,與append()搭配使用,會自動補齊至兩邊個數相等。每一次的append都對應dataset.y中的一個數組元素。利用前面創建的比例尺函數計算出值並賦給舉行元素的x、y屬性。具體的代碼如下:
// 矩形之間的間距
var rectMargin = 10;
// 添加矩形
main.selectAll('.bar')
.data(dataset.y)
.enter()
.append('rect')
.attr('class', 'bar')
.attr('x', function(d, i) {
return xScale(dataset.x[i]) + rectMargin;
})
.attr('y', function(d, i) {
return yScale(d);
})
.attr('width', xScale.rangeBand() - 2*rectMargin)
.attr('height', function(d, i) {
return height - padding.top - padding.bottom - yScale(d);
})
.attr('fill', function(d, i) {
return getColor(i);
});
至此,得到了如下圖所示的柱狀圖。

總結
以上就是利用D3.js實現柱狀圖的全部內容,感興趣的朋友們可以自己動手實踐下,這樣更利於大家的理解和學習,希望這篇文章對大家的學習和工作能有所幫助。如果有疑問大家可以留言交流,謝謝大家對的支持,小編還會陸續更新關於D3.js的文章,請繼續關注。