【D3.js】proxyを使ってデータセットが変更されたらチャートを再描画する。
- D3v4, Javascript
D3.jsを使ってデータビジュアライゼーションを作成するときにありがちな処理として、入力フォームの値が変更されたらチャートを再描画するというのがあります。
入力フォームのchangeイベントが発火されたらフォームの値を取得してredrawするわけですが、入力項目の数が増えてきたりすると管理が面倒になってきます。
できることなら、入力フォームのイベントとチャートの描画は疎結合にして、データセットが変更されたらチャートを描画するような処理にしたいところです。
ECMAScript 2015にて実装されたproxy機能を使うとオブジェクトの変更を簡単に監視することができます。
※ Proxy Objectは2016/9/6現在、一部のブラウザでしか使用することができません。
Can I use… Support tables for HTML5, CSS3, etc
簡単な使い方
詳細なproxyオブジェクトの機能については、MDNを参照していただくとして、最も単純なgeter,seterの監視処理を試してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
//データセット var data = {} //proxyに設定するハンドラ var proxyHandler = { get: function(target, prop, value){ console.log("get!", target) return target[prop] }, set: function(target, prop, value){ console.log("set!", target) target[prop] = value } } //データセットを束縛したプロキシオブジェクトを生成 var proxy = new Proxy(data, proxyHandler) |
上記のコードは、dataオブジェクトに対してgeter,seterのトラップを定義したハンドラを束縛し、proxyオブジェクトを生成しています。
実際にブラウザのJavaScriptコンソール上でproxyオブジェクトを操作した結果が以下です。
proxyオブジェクトに新たなプロパティを設定するとdataオブジェクトにその内容が反映されているのが見て取れます。
同時にハンドラ内に記述されたconsole.logが実行されています。
proxyオブジェクトを使用することでオブジェクトに簡単にobserveを仕込むことができました。
D3サンプル
proxyハンドラ内にチャートを再描画する処理を挟み込み、データセットに変更があったらチャートを再描画するサンプルです。
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 |
!(function(){ "use strict"; const dataSet = [ {name:"tokyo", value:"100"}, {name:"gunma", value:"200"}, {name:"saitama", value:"300"} ] //バーチャートモジュールを生成 const BarChart = createVBarChart() .margin({top:40, left:100, bottom:40, right:10}) .x(function(d){ return d["name"] }) .y(function(d){ return d["value"] }) //チャートを描画する const selector = d3.selectAll("#chart").datum(dataSet) .call(BarChart) //データセットの内容が変更されたらチャートをアップデートする const proxyHandler = { get: function(target, name, value){ return target[name] }, set: function(target, name, value){ if (name == "value" && isNaN(+value)) throw new TypeError("型がちがうよ") target[name] = value selector.update(dataSet) //チャートアップデート } } //データセットをネストし、proxyで包む const nested = d3.nest() .rollup(function(d){ return new Proxy(d[0], proxyHandler) }) .key(function(d){ return d.name }) .map(dataSet) //テキストボックスの値が変更されたらデータセットをporxy経由で変更する const updateDataset = function() { nested["$"+this.name].value = this.value } const textBox = d3.selectAll(".input") .on("change", updateDataset) //テキストボックスに初期値を渡す。 textBox.each(function(){ this.value = nested["$"+this.name].value }) }()); |
関連記事
-
-
配列とarguments
引き続き「テスト駆動JavaScript」本を読んで勉強しているのですが、ちょっ …
-
-
iphoneに搭載されているセンサー(GPS位置情報、ジャイロセンサー、電子コンパス、加速度センサー)の情報を取得
現時点における、モバイルデバイスの各センサーから情報を取得する方法を確認してみま …
-
-
documentオブジェクトの拡張
昨日、めちゃくちゃなコードを作っていて知った副産物 documentオブジェクト …
-
-
[Autocomplete] かな入力で名前(漢字)を絞り込むセレクトボックス
example 入力した「ひらがな」を元に名前(漢字)の一覧を絞り込むセレクトボ …
-
-
エンジニアが正しく「I love you」と伝えるための遺伝的アルゴリズム(殺伐)
「エンジニアが正しく「好き」と伝えるための実装法」という記事が話題だったので、乗 …
-
-
Gunma.web #14で発表したスライド「canvasで遊ぼう!」
遅くなりましたがGunma.web #14で発表したスライドです。 「canva …
-
-
JavaScriptのWith文を使っちゃいけない訳
「JavaScript: The Good Parts」の中で「With文使うん …
-
-
【英語】Kindleで買えるお勧めHTML5 Canvas技術書【読めない】
Kindleでは海外の技術書が手軽に買えてありがたいですね。 最近買った本の中か …
-
-
JavaScript Ninjaは全てのフロントエンドエンジニアが一度は読んでおくべき本
JavaScript Ninjaの極意 ライブラリ開発のための知識とコーディング …
-
-
「SVG Crowbar」表示されているインラインSVG要素を抜き出してSVGファイルとして保存するブックマークレット
SVG Crowbar HTMLドキュメントの中に埋め込まれているSVG要素を抜 …