この記事はD3.js Advent Calendar 2013の9日目です。Open Dataと大きなことを言いましたが、今回は行政データの基本のキであるところの地図を描画してみます。なわけで地図を描画するところがゴールです。
今回の完成図は下記です。国土交通省から神奈川県の行政区域データを取得しD3.jsで描画します。ついでにホームタウンとしているJリーグチーム毎に色塗りしてみました。(マリノスの最終節については触れるべからず!)
サンプルページはこちら
D3 Geo Projection
D3.jsには地理描画機能がデフォルトで含まれており、さまざまな投影法によって地形データを描画することができます。
https://github.com/mbostock/d3/wiki/Geo-Projections
この機能を使って地図を描画します
データの入手
まずは国土交通省のページから行政区域データをダウンロードします
神奈川県のデータであれば N03-130401_14_GML.zip というファイルになります
シェープファイル(.shp)をGeoJSON形式に変換する
D3.jsonで読み込めるデータはGeoJSONまたはTopoJSON形式となります。TopoJSON形式の方が圧縮効率が高いのですが、加工に一手間かかるためここでは基本のGeoJSON形式を扱うことにします。
GDAL(Geospatial Data Abstraction Library)のインストール
前述の国土交通省からダウンロードできるデータにはシェープファイル(拡張子.shp)が含まれています。それをもとにGeoJSONに変換するためのにはogr2ogrというユーティリティが必要であるため、それを含むGDALというライブラリをインストールします。Macであれば下記コマンドで入ります。
$ brew install gdal
GeoJSONへの変換
GDALがインストールできたら下記のコマンドを使ってjson形式に変換します
$ ogr2ogr -f GeoJSON kanagawa.json N03-13_14_130401.shp
一点注意ですが、コンバートされたファイルはshift_jisエンコードとなっています。適宜エディタなど使ってutf-8に変換してください
これでデータの準備はできました。
コード
もっともシンプルな形を想定し単純に地図を描画する例は下記になります
html
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<div id="map"></div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="mapping.js"></script>
</body>
JS
Geo Paths APIを使ってGeoJSONデータを読み込む毎にsvgのpath要素として描画していきます。
(function() {
var g,
width = 900,
height = 650;
// svg要素を作成し、データの受け皿となるg要素を追加している
map = d3.select('#map').append('svg')
.attr('width', width)
.attr('height', height)
.append('g');
// 同じディレクトリにあるgeojsonファイルをhttp経由で読み込む
d3.json("kanagawa.json", function(json) {
var projection,
path;
// 投影を処理する関数を用意する。データからSVGのPATHに変換するため。
projection = d3.geo.mercator()
.scale(45000)
.center(d3.geo.centroid(json)) // データから中心点を計算
.translate([width / 2, height / 2]);
// pathジェネレータ関数
path = d3.geo.path().projection(projection);
// これがenterしたデータ毎に呼び出されpath要素のd属性に
// geoJSONデータから変換した値を入れる
map.selectAll('path')
.data(json.features)
.enter()
.append('path')
.attr('d', path)
.attr("fill", function(d){
// 適当に色を塗るなど
return "hsl(0,0%,80%)";
})
.attr("stroke","hsl(80,100%,0%)" )
.on('mouseover', function(d){
// mouseoverの時のインタラクション
})
.on('click', function(d) {
// clickされた時のインタラクション
});
});
})();
これに多少の色づけをしたのがこちらのサンプルページです。ぜひ見てみてください。
次回予告
地図も描画できるようになったので次回はデータをプロットして新たな知見が得られるようなビジュアライズをめざします!(多分!)