チュートリアル 「D3.jsとTopoJSONで地図を作る」を元に日本地図を作ってみる。
やりたいこと
前回は http://ja.d3js.node.ws/blocks/mike/map/ をに従ってイギリスの地図を作成しました。イギリスでは、いまいち実感がなく、チュートリアルの序盤で行うデータ作成がイギリスを対象にしていたからです。それならば日本を対象にしてデータを作成して、日本地図を作って見ます。
小笠原諸島が「Bonin island」であり、南方諸島が「Volcano island」 なので外国の人が作ったことを窺わせる名称になっています。
できあがったもの
日本の行政区には関係がなく、島を単位にしたデータのようです。d3.jsで日本地図を作る方法を調べると 国土数値情報 行政区域データの詳細 のデータを使う理由を納得できました。
実際のページ http://huruyosiathatena.github.io/d3js_map01/map_mercator_jp.html
ソースコード https://github.com/huruyosiathatena/d3js_map01/tree/master
チュートリアルからの変更
データ作成
下の方法でtopojsonを作ります。
$ ogr2ogr -f GeoJSON -where "adm0_a3 = 'JPN'" subunits_jp.json ne_10m_admin_0_map_subunits.shp $ ogr2ogr -f GeoJSON -where "iso_a2 = 'JP' " places_jp.json ne_10m_populated_places.shp $ topojson --id-property SU_A3 -p NAME=name -p NAME -o jp.json subunits_jp.json places_jp.json
地図の投影方法と中心位置を変更
メルカトル法にして、中心位置を東経135度、北緯35度にしました。
var projection = d3.geo.mercator() .center([135, 35]) .scale(2400) .translate([width / 2, height / 2]);
色付け
d3.jsが提供する d3.scale.category20() を使うことにしました。
オブジェクト名変更
理由が分からないのですが、topojsonのobjectsの下にあり、形状のsubunits
と地名のplaces
のオブジェクト名に「_jp」がついていました。
全体のソース
<!DOCTYPE html> <meta charset="utf-8"> <style> .subunit-boundary { fill: none; stroke: #777; stroke-dasharray: 2,2; stroke-linejoin: round; } .place, .place-label { fill: #444; } text { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 10px; pointer-events: none; } .subunit-label { fill: #777; fill-opacity: .5; font-size: 20px; font-weight: 300; text-anchor: middle; } </style> <body> <script src="http://d3js.org/d3.v3.min.js"></script> <script src="http://d3js.org/topojson.v0.min.js"></script> <script> var width = 960, height = 1160; var color = d3.scale.category20(); var projection = d3.geo.mercator() .center([135, 35]) .scale(2400) .translate([width / 2, height / 2]); var path = d3.geo.path().projection(projection); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); d3.json("jp.json", function(error, jp) { console.log(jp); // 国を表示 svg.selectAll(".subunit") .data(topojson.object(jp, jp.objects.subunits_jp).geometries) .enter() .append("path") .attr("class", function(d){ console.log(d.id);return "subunit "+ d.id; } ) .attr("d", path) .attr("fill", function(d,i){ return color(i);}); // 都市名の○を表示 svg.append("path") .datum(topojson.object(jp, jp.objects.places_jp)) .attr("d", path) .attr("class", "place"); // 都市名を表示 svg.selectAll(".place-label") .data(topojson.object(jp, jp.objects.places_jp).geometries) .enter().append("text") .attr("class", "place-label") .attr("transform", function(d) { return "translate(" + projection(d.coordinates) + ")"; }) .attr("dy", ".35em") .text(function(d) { return d.properties.NAME; }); // 都市名を左側と右側で外に向かうようにする svg.selectAll(".place-label") .attr("x", function(d) { return d.coordinates[0] > 135 ? 6 : -6; }) .style("text-anchor", function(d) { return d.coordinates[0] > 135 ? "start" : "end"; }); // ラベル表示 svg.selectAll(".subunit-label") .data(topojson.object(jp, jp.objects.subunits_jp).geometries) .enter().append("text") .attr("class", function(d) { return "subunit-label " + d.id; }) .attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; }) .attr("dy", ".35em") .text(function(d) { return d.properties.NAME; }); }); </script>