グリッド上に配置されている円「●」にマウスカーソルがのったとき、ツールチップを表示します。グラフ上で表現できる情報には限りがあります。より多くの情報を表示したいときはツールチップが便利です。
サンプルコードの実行結果はこちら
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 |
<!DOCTYPE html> <head> <meta charset="utf-8"> <title>散布図のデータをマウスオーバーしたときにツールチップを表示する</title> <script src="../js/d3.js"></script> <style> svg{ width:360px; height:360px; border:2px solid red;} .mark{ fill:red; stroke:none;} .axis text{font-size:12px;} .axis path, .axis line{ fill:none; stroke:black; } .grid{ stroke: gray; stroke-dashaaray: 5,2; shape-rendering: crispEdges; } .tip{ position:absolute; top:0px; left:0px; z-index:10000; visibility:hidden; border:2px solid black; background-color:pink; width:64px; height:16px; overflow:hidden; text-align:center; font-size:10px; font-family:"メイリオ"; color:black; } </style> </head> <body> <h2>散布図を表示する</h2> <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 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 |
/* 散布図を表示する */ var svgWidth = 320; // SVG要素の幅 var svgHeight = 300; // SVG要素の高さ var offsetX = 30; // X座標のずれ var offsetY =-20; // Y座標のずれ var svg = d3.select("#graph"); var arrData = [ [16,32],[64,48],[128,92],[70,150],[120,300], [45,90],[110,160],[300,20],[180,180],[15,145] ]; var circleElements = svg .selectAll("circle") // circle要素を追加 .data(arrData); circleElements .enter() .append("circle") // CSSクラスを指定 .attr("class","mark") .attr("cx",function(d,i){ return d[0] + offsetX; // 1番目の要素をX表に指定 }) .attr("cy",function(d,i){ return svgHeight - d[1] - offsetY; // 2番目の要素をY座標に指定 }) .attr("r",4); // 点の半径 // アニメーション後の散布図に使用するデータを再設定 function generateData(data){ var result = data .map(function(d,i){ // 配列の要素数だけ繰り返す var x = Math.random() * svgWidth; // X座標を設定 var y = Math.random() * svgHeight; // Y座標を設定 return [x, y]; }); return result; } // 散布図を更新する関数 function generateGraph(){ circleElements .data(arrData) .transition() .attr("cx",function(d,i){ return d[0] + offsetX; }) .attr("cy",function(d,i){ return svgHeight - d[1] - offsetY; }); } function drawScale(){ var maxX = d3.max(arrData,function(d,i){ /* 以下のようにd[ ]の添字を0を指定すると X座標の最大値を求めることができます。 */ return d[0]; // X座標 }); var maxY = d3.max(arrData,function(d,i){ /* 以下のようにd[ ]の添字を1を指定すると Y座標の最大値を求めることができます。 */ return d[1]; // Y座標 }); // 縦の目盛りを表示するために縮尺設定 var yScale = /* 上記で求めた最大値maxYをここで使用する。 */ d3.scale.linear() // 縮尺設定 .domain([0, maxY]) // 元データの範囲 .range([maxY, 0]); // 実際の出力サイズ // 目盛りを表示 svg.append("g") .attr("class","axis") .attr("transform","translate(" + offsetX + ", " + ( svgHeight - maxY - offsetY ) + ")" ) .call( d3.svg.axis() .scale(yScale) .orient("left") .ticks(20) ); // 横の目盛りを表示するために縮尺設定 var xScale = /* 上記で求めた最大値maxXをここで使用する。 */ d3.scale.linear() // 縮尺設定 .domain([0, maxX]) // 元データの範囲 .range([0, maxX]); // 実際の出力サイズ // 目盛りを表示 svg.append("g") .attr("class","axis") .attr("transform","translate(" + offsetX + ", " + ( svgHeight - offsetY ) + ")" ) .call( d3.svg.axis() .scale(xScale) .orient("bottom") ); // グリッドを表示 var grid = svg.append("g"); // 横方向と縦方向のグリッド間隔を自動生成 var rangeX = d3.range(50, maxX, 50); var rangeY = d3.range(20, maxY, 20); // 縦方向のグリッドを作成 grid.selectAll("line.y") .data(rangeY) .enter() .append("line") .attr("class","grid") // (x1,y1) - (x2,y2) の座標値設定 .attr("x1", offsetX) .attr("y1", function(d,i){ return svgHeight - d - offsetY; }) .attr("x2", maxX + offsetX) .attr("y2", function(d,i){ return svgHeight - d - offsetY; }); // 横方向のグリッドを作成 grid.selectAll("line.x") .data(rangeX) .enter() .append("line") .attr("class","grid") // (x1,y1) - (x2,y2) の座標値設定 .attr("x1", function(d,i){ return d + offsetX; }) .attr("y1", svgHeight - offsetY) .attr("x2", function(d,i){ return d + offsetX; }) .attr("y2", svgHeight - offsetY - maxY); // ツールチップを作成 var toolTip = d3.select("body") .append("div") .attr("class","tip"); // ツールチップを表示 circleElements .on("mouseover",function(d){ var x = parseInt( d[0] ); // 円のX座標 var y = parseInt( d[1] ); // 円のY座標 var data = d3.select(this).datum(); // 要素データを読み出す var dx = parseInt( data[0] ); // 円のX座標。変数xと同じ値 var dy = parseInt( data[1] ); // 円のY座標。変数yと同じ値 toolTip .style("left", offsetX + x + "px" ) .style("top", svgHeight + 40 - y + "px") .style("visibility","visible") .text( dx + ", " + dy ); }) .on("mouseout",function(){ toolTip.style("visibility","hidden"); }) } drawScale(); // 一定時間後に行う処理 setInterval(function(){ arrData = generateData( arrData ); // データを更新 generateGraph(); // グラフの更新(アニメーション) },3000); |
ツールチップはDOM要素を利用して表示するので、以下ようにスタイルシートを設定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
.tip{ position:absolute; top:0px; left:0px; z-index:10000; visibility:hidden; border:2px solid black; background-color:pink; width:64px; height:16px; overflow:hidden; text-align:center; font-size:10px; font-family:"メイリオ"; color:black; } |
表示するツールチップは、予めHTMLファイル内にdiv要素を用意することができますが、今回はプログラムを利用して生成します。
サンプルコードの実行結果はこちら
要素の生成にはいつも通りappend()メソッドを使います。DOM要素もappend()メソッドで生成することができます。attr()メソッドで、HTML側で書いた、class属性に「tip」CSSクラス名を設定します。
1 2 3 |
var toolTip = d3.select("body") .append("div") .attr("class","tip") |
散布図の円に関するデータはcircleElementsに格納されていますので、それに.on()メソッドを使い、マウスカーソルが重なった時の処理を書きます。
1 2 3 4 |
circleElements .on("mouseover",function(d){ ... }) |
上記のon()メソッドで設定したイベントハンドラ(関数)には、マウスカーソルが重なった要素(今回は円)のデータが渡されます。このデータはdata()メソッドにより設定されたデータです。ということは、datumd()メソッドを利用して読み出すことができるデータです。
座標軸を整数に変換する。
1 2 |
var x = parseInt( d[0] ); var y = parseInt( d[1] ); |
円データはdatum()メソッドで読み出す。
1 2 3 |
var data = d3.select(this).datum(); var dx = parseInt( data[0] ); var dy = parseInt( data[1] ); |
ツールチップの内容を書き換えるのはtext()メソッドでできます。
1 2 3 4 5 |
toolTip .style("left", offsetX + x + "px" ) .style("top", svgHeight + offsetY - y + "px") .style("visibility",visible) .text( dx + ", " + dy ) |
マウスカーソルが離れたらツールチップを非表示にする処理です。
1 2 3 |
.on("mouseout",function(){ toolTip.style("visibility","hidden") }) |