次の棒グラフにクリックイベントを追加し、バーがクリックされるとアラートメッセージを表示するように実装してみます。
目次
1.全体のコード
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 |
<!DOCTYPE html> <html> <head> <title>d3 click event</title> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="js/d3.min.js"></script> <style type="text/css"> .bar { fill: steelblue; } .axis text { font: 10px sans-serif; color: #333; } </style> </head> <body> <svg id="chart"></svg> <script> var data = [ {name:"A", value:"100"}, {name:"B", value:"150"}, {name:"C", value:"200"}, {name:"D", value:"250"}, {name:"E", value:"300"} ]; // ① グラフ全体の設定 // マージンの設定 var margin = {top: 50, right: 50, bottom: 50, left: 50}; // マージンを除いた描画幅を設定 var width = 500 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; // グラフの全体設定 var chart = d3.select("#chart") .attr("width", width + margin.left + margin.right) // SVG領域は、余白を含む幅 .attr("height", height + margin.top + margin.bottom) // SVG領域は、余白を含む高さ .append("g") // 余白を適用するためのグループを作成(適用された属性は子要素に継承される) .attr("transform", "translate(" + (margin.left) + "," + margin.top + ")"); // ② X軸の設定 // X軸のデータ範囲などバンドスケールを作成 var x = d3.scaleBand() .domain(data.map(function(d) { return d.name; })) // A,B,C,D,E .range([0, width]) // 描画幅 .padding(0.1); // グラフの間隔 // X軸を追加 var xAxis = d3.axisBottom(x); chart.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") // 左上が(0,0)。 X軸をグラフの下部に表示するには、描画領域の高さ分下げる .call(xAxis); // scaleBandを設定 // ③ Y軸の設定 // Y軸のデータ範囲などリニアスケールを作成 var y = d3.scaleLinear() .domain([0, d3.max(data, function(d) { return d.value; })]) // 0 〜 300 .range([height, 0]); // 最大、最小 // Y軸を追加 var yAxis = d3.axisLeft(y); chart.append("g") .attr("class", "y axis") .call(yAxis); // scaleLinearを設定 // ④ 各データを描画 chart.selectAll(".bar") .data(data) // 描画データ .enter().append("rect") .attr("class", "bar") .attr("x", function(d) { return x(d.name); }) .attr("y", function(d) { return y(d.value); }) .attr("height", function(d) { return height - y(d.value); }) .attr("width", x.bandwidth()); // ⑤ イベントを設定 d3.selectAll("rect").on("click",function(data,idx,elem){ var msg = "data:" + data.value + " idx:" + idx + " elem:" + elem + " d3.event.pageX: " + d3.event.pageX + " d3.mouse: " + d3.mouse(this) ; alert(msg); }); </script> </body> </html> |
2.コードの詳細( HTML )
グラフを表示する場所を定義します。
1 |
<svg id="chart"></svg> |
3.コードの詳細( JavaScript )
3−1.グラフ全体の設定
グラフ全体の設定では、グラフを描画する領域のサイズと余白を定義します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// ① グラフ全体の設定 // マージンの設定 var margin = {top: 50, right: 50, bottom: 50, left: 50}; // マージンを除いた描画幅を設定 var width = 500 - margin.left - margin.right, height = 400 - margin.top - margin.bottom; // グラフの全体設定 var chart = d3.select("#chart") .attr("width", width + margin.left + margin.right) // SVG領域は、余白を含む幅 .attr("height", height + margin.top + margin.bottom) // SVG領域は、余白を含む高さ .append("g") // 余白を適用するためのグループを作成(適用された属性は子要素に継承される) .attr("transform", "translate(" + (margin.left) + "," + margin.top + ")"); |
領域全体の大きさは、高さ 400px、幅 500pxの領域で、上下左右に 50pxの余白があります。図にすると次のようになります。
ポイントは 次の箇所になります。
1 2 |
.append("g") // 余白を適用するためのグループを作成(適用された属性は子要素に継承される) .attr("transform", "translate(" + (margin.left) + "," + margin.top + ")"); |
グループを追加し、そのグループ配下の要素に余白分(左・上)移動するようにしています。
3−2.X軸の設定
X軸に表示する実際の値(domain)、描画する幅(range)、グラフの間隔(padding)を設定します。
その設定値を用いて、軸用のグループ要素(g)をグラフに追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// ② X軸の設定 // X軸のデータ範囲などバンドスケールを作成 var x = d3.scaleBand() .domain(data.map(function(d) { return d.name; })) // A,B,C,D,E .range([0, width]) // 描画幅 .padding(0.1); // グラフの間隔 // X軸を追加 var xAxis = d3.axisBottom(x); chart.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") // 左上が(0,0)。 X軸をグラフの下部に表示するには、描画領域の高さ分下げる .call(xAxis); // scaleBandを設定 |
3−3.Y軸の設定
Y軸もX軸同様に設定を行い、軸用のグループ要素(g)をグラフに追加します。
1 2 3 4 5 6 7 8 9 10 11 |
// ③ Y軸の設定 // Y軸のデータ範囲などリニアスケールを作成 var y = d3.scaleLinear() .domain([0, d3.max(data, function(d) { return d.value; })]) // 0 〜 300 .range([height, 0]); // 最大、最小 // Y軸を追加 var yAxis = d3.axisLeft(y); chart.append("g") .attr("class", "y axis") .call(yAxis); // scaleLinearを設定 |
3−4.各データを描画
最後に、各データを描画します。
1 2 3 4 5 6 7 8 9 |
// ④ 各データを描画 chart.selectAll(".bar") .data(data) // 描画データ .enter().append("rect") .attr("class", "bar") .attr("x", function(d) { return x(d.name); }) .attr("y", function(d) { return y(d.value); }) .attr("height", function(d) { return height - y(d.value); }) .attr("width", x.bandwidth()); |
x:座標のどの位置(x)から描画するか
y:座標のどの位置(y)から描画するか
height:描画する高さ
width:描画する幅
3−5.クリックイベントを追加
イベント処理は、selection.on(typenames[, listener[, options]]) を使用して行います。
今回は次のように、全てのrect要素に対して、clickイベント発生時の処理を追加しています。
1 2 3 4 5 |
// ⑤ イベントを設定 d3.selectAll("rect").on("click",function(data,idx,elem){ var msg = "data:" + data.value + " idx:" + idx + " elem:" + elem + " d3.event.pageX: " + d3.event.pageX + " d3.mouse: " + d3.mouse(this) ; alert(msg); }); |
イベント発生時に実行する関数には引数が設定でき
第1引数:要素のデータ
第2引数:インデックス
第3引数:イベントが発生した要素(Node List)
が設定されます。
また、関数内では、d3.event や d3.mouse でイベントが発生した座標などの情報も取得することができます。
今回は、クリックイベントを実装しましたが、typenames にはクリックイベント以外にも、ブラウザが対応している任意のDOMイベントを指定することができます。
設定できるイベントは、こちら(Event reference) を参照して下さい。
4.まとめ
棒グラフに、クリックイベントを追加しました。
selection.on を使用すると様々な要素にイベントが登録できるので、色々と応用ができると思います。