始める前に

地図描画のハードルは結構高く、簡単に実装とはいきません。
理解に役立つ記事をまとめておくので、分からない部分があったら色んな記事を読んで理解して下さい。

また、今回作成したコードは以下のリンクから確認できます。
これを見ながら解説を読むと、多少分かりやすいかと思います。

記事は「地図データの作成」と「コードの実装」部分に分かれています。それでは、頑張りましょう。

地図データの作成

ツールの準備

何はともあれ、以下のようにgdal, jq, topojsonを入手します(jqは無くてもいいです)。

brew install gdal
brew install jq
sudo npm install -g topojson

それぞれのツールの役割は

  • gdal – ogr2ogrを用いて、SHAPEファイルをGeoJSONファイルに変換する
  • jq – jsonファイルの中身を確認する
  • topojson – GeoJSONファイルをTopoJSONファイルに変換する

MacでHomebrewが入っていれば簡単ですが、他の人は……頑張って入れて下さい^^;

データの入手

次に、地図の元データを入手します。Natural Earthから

Admin 1 – States, Provinces -> Download states and provinces

で、zipをファイルを入手できるので、解凍してne_10m_admin_1_states_provinces.shpというファイルがあるか確認します。

ここに各国の都市データが入っています。これをGeoJSONに変換し、日本の県のみを抽出します。

データの変換

gdalに含まれていたogr2ogrというコマンドを用いて、japan.geojsonというファイルを作成します。

ogr2ogr -f GeoJSON -where 'geonunit = "Japan"' japan.geojson ne_10m_admin_1_states_provinces.shp

正しく生成できているか、以下のコマンドで確認します。
日本の県名がずらっと出ればOKです(nullが2つあるかもですが、気にしないで下さい)。

cat japan.geojson | jq '.features[].properties.name_local'

次に、japan.geojsonを以下のコマンドでTopoJSONに変換します。
この時、.geojsonより前のファイル名(この場合japan)を覚えておいて下さい。この後で使います。

topojson -o japan.topojson japan.geojson

これで

  • japan.geojson
  • japan.topojson

というGeoJSONとTopoJSONのファイルができました。
データの準備は完了です。

コードの実装

GeoJSONで描画

まずは、GeoJSONのファイルを使って描画してみます。コードはこちらにあるので、それを見ながら解説を読んで下さい。

まず、d3のjsonメソッドでデータを読み込みます。

d3.json("japan.geojson", function (error, jpn) {

この場合、jpnにデータが格納されています。次に、投影法を設定します。

var projection = d3.geo.mercator()
    .center([137, 34])
    .scale(900)
    .translate([width / 2, height / 2]);

詳しいことは分かりませんが、上記のコードの読み方は

  • mercator() – 投影法にメルカトル図法を用いる
  • center() – 地図の中心は経度137度、緯度34度(三重県あたり)
  • scale() – 大きさは900(数字が大きいほど拡大される)
  • translate() – 描画場所をsvg領域の中央に移動

といった感じでしょうか。次に、地図の描画で使うpathを設定します。
この時、先ほど作ったprojectionを渡してあげます。

var path = d3.geo.path()
    .projection(projection);

最後に描画をします。
jpn.featuresの中にデータが入ってるので、それを渡します。
d属性に先ほど作ったpathを渡せば、あとはD3が良きに計らってくれます(すごい!)。

svg.selectAll("path")
    .data(jpn.features)
    .enter()
    .append("path")
    .attr("stroke", "white")
    .attr("stroke-width", "0.5")
    .attr("d", path);

TopoJSONで描画

次は、TopoJSONのファイルを使って描画します。コードはこちらにあります。
GeoJSONの時とほぼ同じなので、違う部分だけを説明します。

新しく以下のコードが追加されています。

var features = topojson.object(jpn, jpn.objects.japan);

topojson.objectメソッドで、TopoJSONを扱いやすい形に戻します。
ここで、第二引数のjpn.objects.~~~の部分に、データの変換の際に使った名前が入ります。

これを使って描画をします。

svg.selectAll("path")
    .data(features.geometries)
    .enter()
    .append("path")
    .attr("stroke", "white")
    .attr("stroke-width", "0.5")
    .attr("d", path);

.geometriesにデータが入ってるので、これを渡してあげれば後は勝手に描画してくれます(すごい!)。

まとめ

大分長くなりましたが、これで生成から描画まで、一通りできるようになったと思います。
何となく、

  • GeoJSONはデータ量が多いが、扱いやすい
  • TopoJSONはデータ量が少ないが、少し扱いづらい

という感じですかね。時と場合に合わせて使うのが良い気がします。

CATEGORIES