はじめに
あるデータをグラフに描画する必要がありました。
単なるグラフでなく、グラフをクリックすると、該当する場所の値をポップアップで表示したいとの要望です。
自分でWordPressを使っていることもあるせいか、すぐ思いついたのはWebのアクセス統計解析などで使われているグラフでした。
で、探してみたところ、要件に合うのは以外に少なく、
Timeplotは、サーバーサイドだし、データ数が多いと遅いので×。
(TimePlotもローカルで動作するのを確認した。)
HighChartsは、データ数が5000個くらいまでならO.K.ですが、数万個だと遅すぎて×。
個人的にHighChartsが好きだったのですが、遅いのが致命的なので、データ数が少ない場合に使うことにします。
結果、Flotを使うことにしました。
今回は付属サンプルにある「interacting.html」を改良して、CSVファイルを読み込んでグラフを表示するようにしました。
CSV(カンマ、又はタブ区切り)のデータは、「jquery.csv.js」を利用して読み込んでいます。
読み込むファイル名をJavaScriptファイルに記述する必要があるのが面倒ですが、暇を見つけてユーザが指定出来るように改造しようと思います。
今回は散布図なのですが、1個の点が何を表しているのかラベルを付けて、値とともにポップアップで表示させています。
これは、「mydata.js」の「$(“#placeholder”).bind(“plothover”, function (event, pos, item)」で行っています。
「item」オブジェクトが持っている情報は、「API.txt」の633行目あたりに記述されています。
ただ、「IE ver.8」はFlotをtrunk版や、「ExplorerCanvas」を最新のモノに入れ替えても動作しません。(他のバージョンは未確認。)
HighchartsとCSVを使ったグラフの記事もあります。
【追記2010.09.13】
revulo様に紹介頂いた「FlashCanvas」を使うようにソースを修正しました。
環境
- Flot ver.0.6
- JQuery ver.1.3.2
- JQuery ver.1.4.2
- jquery.csv.js ver.1.0
- flashcanvas.js Free edition ver.1.3
今回、必要な機能
- 数万個のデータを(ある程度)ストレス無く扱える。
- グラフをクリックすると、該当する場所の値をポップアップで表示できる。
- CSVなどの外部ファイルからデータを読み込める。
- ローカルで使用可能。
- 散布図(scatter)が描画可能。
- カスタマイズが容易。
- 見た目が綺麗。
サンプルデータ
適当に作ったものです。
js_graph_data.zip
グラフのサンプル
必要なファイル
- Flot(Googleで検索。JQueryも含まれています。)
- サンプルデータ(カンマ、又はタブ区切り)(上記)
- jquery.csv.js(Googleで検索)
- mydata.js(下記)
- XHTMLファイル(下記)
- layout.css(不要かも。Flotの「examples」にあります。)
動作確認
JQueryの「ver.1.3.2」、「ver.1.4.2」の両方で動作したもの。
- WindowsXP pro SP3 32bit
- Mozila Firefox ver.3.6.9
- Opera ver.10.61
- Safari v.5.0.2
- Google Chrome v.6.0.572.55
- Internet Explorer ver.8.0.6001.18702
IEは、「ExplorerCanvas」の代わりに「FlashCanvas」を使って表示出来ることを確認した。
Chromeはローカル×、リモート○。
以下、「ツール」→「JavaScriptコンソール」のエラーメッセージ。
XMLHttpRequest cannot load file:///D:hoge.txt. Origin null is not allowed by Access-Control-Allow-Origin.
動作確認
JQueryの「ver.1.3.2」、「ver.1.4.2」の両方で動作したもの。
- MacOS X ver.10.4.11
- Mozila Firefox ver.3.6.3
- Safari v.4.1.1
itemオブジェクトの情報
「API.txt」の633行目あたりに記述されている。
item: { datapoint: the point, e.g. [0, 2] dataIndex: the index of the point in the data array series: the series object seriesIndex: the index of the series pageX, pageY: the global screen coordinates of the point }
Flot
右上メニューにある「Github」も利用し易い。
http://www.flotcharts.org/
JQuery
FlashCanvas
ExplorerCanvas
html
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html charset=UTF-8" /> <title>Graph</title> <link href="layout.css" rel="stylesheet" type="text/css"></link> <!--[if IE]> <script type="text/javascript" src="./flashcanvas.js"></script> <![endif]--> <!-- <script type="text/javascript" src="./jquery-1.4.2.min.js"></script> --> <script type="text/javascript" src="./flot/jquery.min.js"></script> <script type="text/javascript" src="./flot/jquery.flot.js"></script> <script type="text/javascript" src="./jquery.csv.js"></script> <script type="text/javascript" src="./mydata.js"></script> </head> <body> <h1>Graph</h1> <div id="placeholder" style="width:800px; height:500px"></div> <!-- <p>Try pointing and clicking on the points.</p> <p id="hoverdata">Mouse hovers at (<span id="x">0</span>, <span id="y">0</span>). <span id="clickdata"></span></p> --> </body> </html>
mydata.js
このファイルでデータの読み込みと、グラフの外観、挙動を制御します。
「var csv = $.csv(“\t”)( data );」で、タブ区切りのテキストファイルを読み込んでいます。
「var csv = $.csv()( data );」にすれば、カンマ区切りのテキストファイルを読み込めます。
詳細は、「jquery.csv.js」に記述されています。
以下は、4列のデータであると仮定しています。
サンプルデータは3列しかありませんが、動作には問題ありません。
「jquery.csv.js」は改行コードを指定出来るように改造したものを使っています。
$.get('hoge.txt', function( data ) { var mydata = []; var mydata_label = []; var mydata_des = []; var csv = $.csv("\t")( data ); var digit = 3; // var axix_y_min = 0; // var axix_y_max = 20; // read csv file $( csv ).each( function() { mydata.push( [ parseInt( this[0] ), parseFloat( this[1] ) ] ); mydata_label.push( [ this[2] ] ); mydata_des.push( [ this[3] ] ); }); var plot = $.plot($("#placeholder"), [ { data: mydata, label: "All"} ], { series: { points: { show: true } }, grid: { hoverable: true, clickable: true }, // yaxis: { min: axix_y_min, max: axix_y_max } }); function showTooltip(x, y, c1, c2, c3) { $('<div id="tooltip">;' + c1 + '<br />;' + c2 + '<br />;' + c3 + '</div>;').css( { position: 'absolute', display: 'none', top: y + 5, left: x + 5, border: '1px solid #fdd', padding: '2px', 'background-color': '#fee', opacity: 0.80 }).appendTo("body").fadeIn(200); } var previousPoint = null; $("#placeholder").bind("plothover", function (event, pos, item) { $("#x").text(pos.x.toFixed( digit )); $("#y").text(pos.y.toFixed( digit )); if (item) { if (previousPoint != item.datapoint) { previousPoint = item.datapoint; $("#tooltip").remove(); var x = item.datapoint[0].toFixed( digit ); var y = item.datapoint[1].toFixed( digit ); x = parseInt( x ); // showTooltip(item.pageX, item.pageY, // item.series.label + "->;" + // mydata_label[ item.dataIndex ] + // " " + "(" + x + "," + y + ")"); showTooltip(item.pageX, item.pageY, mydata_label[ item.dataIndex ], "(" + x + " , " + y + ")", mydata_des[ item.dataIndex ]); } else { $("#tooltip").remove(); previousPoint = null; } } }); $("#placeholder").bind("plotclick", function (event, pos, item) { if (item) { $("#clickdata").text("You clicked point array index: " + item.dataIndex + " in " + item.series.label + "."); // $("#clickdata").text("You clicked point " + item.dataIndex + " in " + item.series.label + "."); plot.highlight(item.series, item.datapoint); } }); });
Comments