D3.js實現(xiàn)餅狀圖的方法詳解
前言
小編在之前已經跟大家分享過關于怎樣用柱狀圖和折線圖這兩種基本圖表。這兩種圖表都是有坐標軸的,現(xiàn)在來說一種沒有坐標軸的圖表——餅圖。
餅狀圖實現(xiàn)
還是和之前一樣,我們先把簡單的畫圖框架搭起來,添加SVG畫布。但是這里需要注意的是,為了方便后面畫餅圖上的弧形,我們把組合這些元素的g元素移動到畫布的中心:
<!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> window.onload = function() { var width = 600, height = 300; // 創(chuàng)建一個分組用來組合要畫的圖表元素 var main = d3.select('.container svg').append('g') .classed('main', true) // 注意這里和前面幾種圖表的差別 .attr('transform', "translate(" + width/2 + ',' + height/2 + ')'); }; </script> </body> </html>
模擬數(shù)據(jù)并轉化
為了畫餅圖,我們模擬了一些這樣的數(shù)據(jù)。
// 模擬數(shù)據(jù) var dataset = [ {name: '購物', value: 983}, {name: '日常飲食', value: 300}, {name: '醫(yī)藥', value: 1400}, {name: '交通', value: 402}, {name: '雜費', value: 134} ];
在柱狀圖等有坐標軸的圖表中,我們通過創(chuàng)建合適的比例尺來將模擬好的數(shù)據(jù)轉化成適合畫圖的數(shù)據(jù),那在餅圖里,又用什么來轉化呢?看這里~
// 轉換原始數(shù)據(jù)為能用于繪圖的數(shù)據(jù) var pie = d3.layout.pie() .sort(null) .value(function(d) { return d.value; }); // pie是一個函數(shù) var pieData = pie(dataset);
layout叫做布局,在D3.js中它提供了一些轉化成特定圖表數(shù)據(jù)的函數(shù),如其中就包括餅圖。它提供一個基礎的轉化函數(shù),在此基礎上我們根據(jù)自己的需要再對該函數(shù)進行進一步的設置,就得到了如上述代碼中pie變量保存的函數(shù)一樣的轉化工具,通過把原始的數(shù)據(jù)dataset傳入pie中就能得到繪圖數(shù)據(jù)pieData。
具體的變化我們可以看下圖。
左邊是轉化前的原始的數(shù)據(jù)結構,右邊是轉化后的適合繪圖的數(shù)據(jù)結構??梢钥吹剑诒A粼镜臄?shù)據(jù)的基礎上,轉化后的數(shù)據(jù)新增了該項在整個餅圖中的起始角度(startAngle和endAngle),以及弧形之間的間隙角度(padAngle)。
計算弧形路徑
在餅圖中,我們用SVG中的path元素來表示每一塊弧形,而從pieData到path元素的d屬性還是有一定的距離,所以我還需要再通過一步操作來用pieData計算出d屬性可用的值。
// 創(chuàng)建計算弧形路徑的函數(shù) var radius = 100; var arc = d3.svg.arc() .innerRadius(0) .outerRadius(radius);
添加弧形
上面的代碼用svg.arc()
創(chuàng)建了一個計算弧形路徑的函數(shù),通過這個函數(shù)就可以計算出path的d屬性的值,就像下面這樣。
// 添加弧形 main.selectAll('g') .data(pieData) .enter() .append('path') .attr('fill', function(d, i) { return getColor(i); }) .attr('d', function(d){ return arc(d); });
好了,餅圖就這樣畫好了。
下面給大家分享個實例代碼,實現(xiàn)餅圖中加上下圖這樣的文字標簽。
效果圖
實例代碼
<!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; } polyline { fill: none; stroke: #000000; stroke-width: 2px; stroke-dasharray: 5px; } </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> window.onload = function() { var width = 600, height = 300; // 創(chuàng)建一個分組用來組合要畫的圖表元素 var main = d3.select('.container svg').append('g') .classed('main', true) .attr('transform', "translate(" + width/2 + ',' + height/2 + ')'); // 模擬數(shù)據(jù) var dataset = [ {name: '購物', value: 983}, {name: '日常飲食', value: 300}, {name: '醫(yī)藥', value: 1400}, {name: '交通', value: 402}, {name: '雜費', value: 134} ]; // 轉換原始數(shù)據(jù)為能用于繪圖的數(shù)據(jù) var pie = d3.layout.pie() .sort(null) .value(function(d) { return d.value; }); // pie是一個函數(shù) var pieData = pie(dataset); // 創(chuàng)建計算弧形路徑的函數(shù) var radius = 100; var arc = d3.svg.arc() .innerRadius(0) .outerRadius(radius); var outerArc = d3.svg.arc() .innerRadius(1.2 * radius) .outerRadius(1.2 * radius); var oArc = d3.svg.arc() .innerRadius(1.1 * radius) .outerRadius(1.1 * radius); var slices = main.append('g').attr('class', 'slices'); var lines = main.append('g').attr('class', 'lines'); var labels = main.append('g').attr('class', 'labels'); // 添加弧形元素(g中的path) var arcs = slices.selectAll('g') .data(pieData) .enter() .append('path') .attr('fill', function(d, i) { return getColor(i); }) .attr('d', function(d){ return arc(d); }); // 添加文字標簽 var texts = labels.selectAll('text') .data(pieData) .enter() .append('text') .attr('dy', '0.35em') .attr('fill', function(d, i) { return getColor(i); }) .text(function(d, i) { return d.data.name; }) .style('text-anchor', function(d, i) { return midAngel(d)<Math.PI ? 'start' : 'end'; }) .attr('transform', function(d, i) { // 找出外弧形的中心點 var pos = outerArc.centroid(d); // 改變文字標識的x坐標 pos[0] = radius * (midAngel(d)<Math.PI ? 1.5 : -1.5); return 'translate(' + pos + ')'; }) .style('opacity', 1); var polylines = lines.selectAll('polyline') .data(pieData) .enter() .append('polyline') .attr('points', function(d) { return [arc.centroid(d), arc.centroid(d), arc.centroid(d)]; }) .attr('points', function(d) { var pos = outerArc.centroid(d); pos[0] = radius * (midAngel(d)<Math.PI ? 1.5 : -1.5); return [oArc.centroid(d), outerArc.centroid(d), pos]; }) .style('opacity', 0.5); }; function midAngel(d) { return d.startAngle + (d.endAngle - d.startAngle)/2; } function getColor(idx) { var palette = [ '#2ec7c9', '#b6a2de', '#5ab1ef', '#ffb980', '#d87a80', '#8d98b3', '#e5cf0d', '#97b552', '#95706d', '#dc69aa', '#07a2a4', '#9a7fd1', '#588dd5', '#f5994e', '#c05050', '#59678c', '#c9ab00', '#7eb00a', '#6f5553', '#c14089' ] return palette[idx % palette.length]; } </script> </body> </html>
總結
以上就是利用D3.js實現(xiàn)餅圖的全部內容,希望這篇文章對大家的學習和工作能有所幫助。如果有疑問大家可以留言交流,小編還會陸續(xù)更新關于D3.js的文章,請大家繼續(xù)關注腳本之家。
相關文章
JavaScript中判斷函數(shù)是new還是()調用的區(qū)別說明
具名函數(shù)的各種調用方式 在之前篇幅中已經介紹過了。這篇看看如何判斷一個函數(shù)是被new調用的,還是被其它方式調用的。2011-04-04Javascript基于對象三大特性(封裝性、繼承性、多態(tài)性)
這篇文章主要介紹了Javascript基于對象三大特性,包括封裝性、繼承性、多態(tài)性,感興趣的小伙伴們可以參考一下2016-01-01JavaScript去除空格的三種方法(正則/傳參函數(shù)/trim)
個人認為去除空格最好的方法.采用的是正則表達式,這是最核心的原理,同時呢,還是有其他方法可以辦到的,接下來將介紹一下三種方法(trim)空格,感興趣的朋友可以了解下,或許對你有幫助呢2013-02-02讓網(wǎng)站自動生成章節(jié)目錄索引的多個js代碼
這篇文章主要介紹了讓博客園博客自動生成章節(jié)目錄索引的多個js代碼,需要的朋友可以參考下2018-01-01JavaScript中在光標處插入添加文本標簽節(jié)點的詳細方法
本文主要介紹了JavaScript中在光標處插入添加文本標簽節(jié)點的詳細方法。具有很好的參考價值。下面跟著小編一起來看下吧2017-03-03如何在JavaScript中等分數(shù)組的實現(xiàn)
這篇文章主要介紹了如何在JavaScript中等分數(shù)組的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-12-12