【D3.js】選択されたデータ範囲のグラフを表示する(d3.svg.brush)
下位のグラフで選択された範囲を上位のグラフで拡大表示します。
複雑なことをやっているように見えますが、D3.jsでは比較的簡単に実装することができます。
サンプルコード
データ範囲の選択機能を追加するためにd3.svg.brush()を使用しています。
ヘルパー関数として、こちらの記事で作成した関数を使用しています。
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 |
d3.csv("access.csv", function(data){ var parseDate = d3.time.format("%Y/%m/%d").parse; //データセット型変換 data.forEach(function(d) { d.date = parseDate(d.date); d.access = parseInt(d.access); }); var dateExtent = d3.extent( data.map( F('date') ) ); //dateの最小値・最大値取得 var accessMax = d3.max( data.map( F('access') ) ); //accessの最大値取得 //上位グラフ用、margin, scale, axis設定 var margin = {top: 10, right: 10, bottom: 100, left: 40}; var width = 960 - margin.left - margin.right; var height = 500 - margin.top - margin.bottom; var xScale = d3.time.scale() .domain(dateExtent) .range([0, width]); var yScale = d3.scale.linear() .domain([0, accessMax]) .range([height, 0]); var xAxis = d3.svg.axis().scale(xScale).orient("bottom"); var yAxis = d3.svg.axis().scale(yScale).orient("left"); //下位グラフ用、margin, scale, axis設定 var margin2 = {top: 430, right: 10, bottom: 20, left: 40}; var height2 = 500 - margin2.top - margin2.bottom; var x2Scale = d3.time.scale() .domain(xScale.domain()) .range([0, width]); var y2Scale = d3.scale.linear() .domain(yScale.domain()) .range([height2, 0]); var xAxis2 = d3.svg.axis().scale(x2Scale).orient("bottom"); //上位グラフareaオブジェクト var area = d3.svg.area() .interpolate("monotone") .x(F('date', xScale)) .y0(height) .y1(F('access', yScale)); //下位グラフareaオブジェクト var area2 = d3.svg.area() .interpolate("monotone") .x(F('date', x2Scale)) .y0(height2) .y1(F('access', y2Scale)); //ステージ作成 var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom); //フォーカス時の上位グラフの表示位置調整のためにクリップパスを作成 svg.append("defs").append("clipPath") .attr("id", "clip") .append("rect") .attr("width", width) .attr("height", height); var focus = svg.append("g") //上位グラフグループ作成 .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var context = svg.append("g") //下位グラフグループ作成 .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")"); focus.append("path") .datum(data) .attr("clip-path", "url(#clip)") //クリップパスを適用 .attr("d", area); focus.append("g") //x目盛軸 .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); focus.append("g") //y目盛軸 .attr("class", "y axis") .call(yAxis); context.append("path") //下位グラフ .datum(data) .attr("d", area2); context.append("g") //下位x目盛軸 .attr("class", "x axis") .attr("transform", "translate(0," + height2 + ")") .call(xAxis2); /* *brushは透明なrectをグループ上設置しマウスイベントを取得する。 *設置したrect上ではドラッグで範囲選択が可能 *範囲が選択されている状態でbrush.extent()メソッドを実行するとその範囲のデータ値を返す */ var brush = d3.svg.brush() //brushオブジェクト作成 .x(x2Scale) //x軸を選択可能範囲に指定 .on("brush", brushed); context.append("g") //brushグループを作成 .attr("class", "x brush") .call(brush) .selectAll("rect") .attr("y", -6) .attr("height", height2 + 7); function brushed() { console.log( brush.extent()); xScale.domain(brush.empty() ? x2Scale.domain() : brush.extent()); //選択されたデータセットの範囲をxScaleのdomainに反映 focus.select("path").attr("d", area); //上位グラフアップデート focus.select(".x.axis").call(xAxis); //上位x軸アップデート } }); |
ちょっとだけ解説
1 2 3 |
var brush = d3.svg.brush() //brushオブジェクト作成 .x(x2Scale) //x軸を選択可能範囲に指定 .on("brush", brushed); |
brushオブジェクトは、グラフ上にマウスドラッグで範囲選択を行う機能を提供します。
選択対象はxメソッド、yメソッドにscaleオブジェクトを渡すことで設定します。
(xメソッドだけだと横軸のみ、x,y両メソッドにスケールが設定されている場合は縦横の選択が可能になります)
brushイベントは選択時に呼ばれます。
1 2 3 4 5 6 |
function brushed() { //選択されたデータセットの範囲をxScaleのdomainに反映 xScale.domain(brush.empty() ? x2Scale.domain() : brush.extent()); focus.select("path").attr("d", area); //上位グラフアップデート focus.select(".x.axis").call(xAxis); //上位x軸アップデート } |
brushイベントによって呼ばれたコールバックの中では、brush.extent()メソッドによって選択されたデータ値を取得し、その値でxScaleのドメインを更新します。
xScaleが適用されている上位グラフと上位x軸(xaxis)のアップデートを行うことで、下位グラフで選択された範囲のデータを上位グラフ上で表示されます。