以前、縦棒グラフを表示するサンプルコードを書きましたが、時と場合によりただ棒グラフを表示するだけではなく、インタラクティブに表現したいことがあります。たとえば、棒グラフで商品別の売り上げを表示する時、売れている順番に並び替えたいときです。
サンプルコードの実行結果はこちら
目盛りとスケールの準備
都市名・人口のデータセットとしてのCSVファイルを作成します。
最初の列が都市名、2行目が人口の数値です。
1 2 3 4 5 6 7 8 9 10 |
city,people Tokyo,12000 Yokohama,7000 Osaka,6500 Chiba,3500 Kyoto,2000 Fukuoka,1500 Hiroshima,1200 Nagoya,2200 Saitama,3000 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<!DOCTYPE html> <head> <meta charset="utf-8"> <title>並び替え機能を付き縦棒グラフ</title> <script src="../js/d3.js"></script> <style> svg{ width:640px; height:480px; border:2px solid black; background-color:#ffffff; padding:16px 16px 16px 16px; } .bar{fill:orange;} .barNum, .barName{ font-size:10px; text-anchor:middle; } .axis path, .axis line, .axis_x line{ fill:none; stroke:black; } </style> </head> <body> <h1>縦棒グラフを表示</h1> <form> <input type="checkbox" id="dataSort">並び替え</input> </form> <svg id="graph"></svg> <script src="test.js"></script> </body> </html> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
/* 並び替え機能をつけて棒グラフを表示する */ // HTMLファイルで設定した#graphの要素の幅、高さを取得する var svgEle = document.getElementById("graph"); var svgWidth = getComputedStyle( svgEle, null) .getPropertyValue("width"); var svgHeight = getComputedStyle( svgEle, null) .getPropertyValue("height"); svgWidth = parseFloat( svgWidth ); // 整数に変換する svgHeight = parseFloat( svgHeight ); // 整数に変換する var offsetX = 40; // X座標のずれ var offsetY = 20; // Y座標のずれ var barEle; // 棒グラフの棒の要素を格納 var barwidth = 25; var barMargin = 30; var xScale; var yScale; var axisXEle; var axisYEle; d3.csv("test.csv", /* d3.csv()メソッドの第2パラメーターに関数を指定すると、 データを読み込む前に処理をすることができます、row()メソッドと使うと 日本語名のヘッダーを使い、変数名に置き換えることができます。 読み込まれたデータは文字列になるので整数に変換します。 */ function(row){ return { city: row.city, population : parseInt(row.people) } }, function(error,csvData){ var maxNum = d3.max( csvData.map(function(d,i){ // データの最大値を計算 return d.population; }) ); /* 最大値を1.1倍にして、 一番長い棒グラフがsvgの枠線と重ならないようにする */ maxNum *= 1.1; /* 目盛りを表示するためにスケール設定 d3.scale.ordinal()を使い、連続した数値意地がの目盛り/ラベルを 利用できます。ということは目盛り/ラベルをdomain(["abc","da","gage"]) と書くことができます。domain()メソッドのパラメーターには、 csvData.map()メソッドを指定して、city名のみ抽出するようにしてます。 */ xScale = d3.scale.ordinal() .domain( csvData.map(function(d,i){ return d.city; }) // cityを設定 ) /* 縦棒の幅、間隔、目盛りを表示するには、 rangeRoundBands()メソッドを指定できます。 第1パラメーター: 配列形式で表示範囲を指定し、 第2パラメーター: 隙間の割合を指定する。0.1なら10%、1.0なら100%です。 */ .rangeRoundBands([ 0, svgWidth], 0.6); // 幅を指定 // 目盛りを表示するためにスケール設定 yScale = d3.scale.linear() .domain([ 0, maxNum]) .range([ svgHeight, 0]); // データを描画 barEle = d3.select("#graph") .selectAll("rect") .data(csvData); // データの追加 barEle.enter() .append("rect") .attr("class","bar") .attr("width", xScale.rangeBand() ) .attr("height",0) .attr("x", function(d,i){ return xScale(d.city) + offsetX; }) .attr("y", function(d,i){ return svgHeight - offsetY; }) .transition() .duration(600) .attr("height", function(d,i){ return svgHeight - yScale( d.population ); }) .attr("y", function(d,i){ return yScale(d.population) - offsetY; }); axisXEle = d3.select("#graph") .append("g") .attr("class","axis") .attr("transform","translate(" + offsetX + ", " + ( svgHeight - offsetY ) + ")") .call( d3.svg.axis() .scale(xScale) .orient("bottom") ); axisYEle = d3.select("#graph") .append("g") .attr("class","axis") .attr("transform","translate(" + offsetX + ", -" + offsetY + ")") .call( d3.svg.axis() .scale(yScale) .orient("left") ); // チェックボックスをクリックした場合のソート処理 d3.select("#dataSort").on("change", function(){ var s; /* sort()メソッドを利用してデータセット内の人口の値をソートします。 sort()メソッドにはソート関数を指定します。このソート関数に データセットのデータが2つ渡されます。この2つの値を比較して、 -1,0,1のいずれか返却することによりソートが実行されます。 */ if( this.checked ){ // 昇順 s = csvData.sort( function(a,b){ return b.population - a.population; }); }else{ // 降順 s = csvData.sort( function(a,b){ return a.population - b.population; }); } /* sortされたとき、縦棒グラフだけではなく、横軸の目盛りに 表示されているcity名も並び替えます。 */ var sortResult = s.map(function(d,i){ return d.city;}); // 並び替えられたcity名をdomain()メソッドに代入 xScale.domain(sortResult); /* 並び替え後の棒グラフと横軸の目盛り/ラベルをの表示処理をする。 call()メソッドを使い再設定する */ axisXEle .call( d3.svg.axis() .scale(xScale) .orient("bottom") ); // sort処理後に縦棒グラフの表示処理を行う barEle .transition() .attr("x",function(d,i){ return xScale(d.city) + offsetX; }); }) }); |