D3.jsとOpen Data〜その１地図を描画する

この記事は[D3.js Advent Calendar 2013](http://www.adventar.org/calendars/117)の9日目です。Open Dataと大きなことを言いましたが、今回は行政データの基本のキであるところの地図を描画してみます。なわけで地図を描画するところがゴールです。

今回の完成図は下記です。国土交通省から神奈川県の行政区域データを取得しD3.jsで描画します。ついでにホームタウンとしているJリーグチーム毎に色塗りしてみました。(マリノスの最終節については触れるべからず！)

![スクリーンショット 2013-12-08 21.03.04.png](https://qiita-image-store.s3.amazonaws.com/0/11025/2ce5c9e1-86a5-f9d9-c8d7-d06cef698cf6.png)
サンプルページは[こちら](http://dl.dropboxusercontent.com/u/9423289/d3sample_01/kanagawa.html)

## D3 Geo Projection

D3.jsには地理描画機能がデフォルトで含まれており、さまざまな投影法によって地形データを描画することができます。

![スクリーンショット 2013-12-08 21.14.03.png](https://qiita-image-store.s3.amazonaws.com/0/11025/a273b2ce-9882-e72b-72e1-860591136cd3.png)
https://github.com/mbostock/d3/wiki/Geo-Projections

この機能を使って地図を描画します

## データの入手

まずは国土交通省のページから行政区域データをダウンロードします

* 国土数値情報: http://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N03.html

神奈川県のデータであれば N03-130401_14_GML.zip というファイルになります

## シェープファイル(.shp)をGeoJSON形式に変換する

D3.jsonで読み込めるデータはGeoJSONまたはTopoJSON形式となります。TopoJSON形式の方が圧縮効率が高いのですが、加工に一手間かかるためここでは基本のGeoJSON形式を扱うことにします。

### GDAL(Geospatial Data Abstraction Library)のインストール

前述の国土交通省からダウンロードできるデータには[シェープファイル](http://www.esrij.com/getting-started/learn-more/shapefile/)(拡張子.shp)が含まれています。それをもとにGeoJSONに変換するためのにはogr2ogrというユーティリティが必要であるため、それを含む[GDAL](http://www.gdal.org/)というライブラリをインストールします。Macであれば下記コマンドで入ります。

```shell-session
$ brew install gdal
```

### GeoJSONへの変換

GDALがインストールできたら下記のコマンドを使ってjson形式に変換します

```shell-session
$ ogr2ogr -f GeoJSON kanagawa.json N03-13_14_130401.shp
```

一点注意ですが、コンバートされたファイルはshift_jisエンコードとなっています。適宜エディタなど使ってutf-8に変換してください

これでデータの準備はできました。

## コード

もっともシンプルな形を想定し単純に地図を描画する例は下記になります

### html

```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](https://github.com/mbostock/d3/wiki/Geo-Paths#wiki-path_projection)を使ってGeoJSONデータを読み込む毎にsvgのpath要素として描画していきます。

```js:mapping.js
(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された時のインタラクション
            });
    });

})();
```

これに多少の色づけをしたのがこちらの[サンプルページ](http://dl.dropboxusercontent.com/u/9423289/d3sample_01/kanagawa.html)です。ぜひ見てみてください。

## 次回予告

地図も描画できるようになったので次回はデータをプロットして新たな知見が得られるようなビジュアライズをめざします！（多分！)

[D3.js Advent Calendar 2013はこちら！](http://www.adventar.org/calendars/117)