Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

D3.jsで日本地図を描き、都道府県別に色を塗る

More than 5 years have passed since last update.

都道府県別のアクセス数みたいなものを、種類別に地図上で塗り分ける、というのをD3.jsでやってみようと思います。

ちなみにD3.jsはぜんぜん知らなかったので、とりあえず基本のチュートリアル地図のチュートリアルを読みました。

ツールのインストール

地図データの変換とかをするためのツールをインストールします。(Macです。)

$ brew install gdal
$ brew install node
$ npm install -g topojson

地図データのダウンロードと変換

Natural Earthから都道府県レベルの地図データをダウンロードします。

http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_1_states_provinces.zip

解凍するとファイルが色々ありますが、ne_10m_admin_1_states_provinces.shp というファイルを指定して日本のデータのGeoJSONファイルを作ります。

$ ogr2ogr -f GeoJSON -where "adm0_a3 = 'JPN'" pref.json ne_10m_admin_1_states_provinces.shp

pref.jsonというファイルができました。
このファイルからTopoJSONファイルを作るのですが、なぜか静岡県の名前がnullになっているので、pref.jsonファイルを開いて、"name":"Shizuoka"になっている行の"name_local":null"name_local":"静岡県"に修正しておきます。
(ちなみに1個目の"name":nullになってる行もよくわからないけど消して良さそう。)

TopoJSONファイルを作ります。

$ topojson -p name -p name_local -p latitude -p longitude -o japan.json pref.json

japan.jsonというファイルができました。

表示データの準備

表示したい都道府県別のデータは、ID => 都道府県名の配列と、ID => アクセス数の配列の2つがPHPであるので、それぞれ使いやすい形にしてJSONにしておきます。

<?php
$pref = array(1 => '北海道', 2 => '青森県', ... , 47 => '沖縄県');
$category = array(
        array(
                'name' => 'カテゴリー1',
                'data' => array(1 => 291, 2 => 19, ... , 47 => 3)
        ),
        ...
        array(
                'name' => 'カテゴリー2',
                'data' => array(1 => 111, 2 => 39, ... , 47 => 24)
        ),
);
?>
<script type="text/javascript">
var pref = <?php echo json_encode(array_flip($pref), JSON_UNESCAPED_UNICODE); ?>;
var category = <?php echo json_encode($category, JSON_UNESCAPED_UNICODE); ?>;

それぞれ、

var pref = {"北海道":1,"青森県":2, ... ,"沖縄県":47};
var category = [{"name":"カテゴリー1","data":{"1":291,"2":19, ... , "47":3}},{"name":"カテゴリー2","data":{"1":111,"2":39, ... , "47":24}}];

のようになります。
地図データに漢字の都道府県名が入っているので、そこからIDを引けるようにしておきます。

D3.js

まず地図を表示。

var width = 900,
    height = 960;

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var projection = d3.geo.mercator()
    .center([136, 35.5])
    .scale(2000)
    .translate([width / 2, height / 2]);

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

d3.json("japan.json", function(error, japan) {
    var topo = topojson.object(japan, japan.objects.pref).geometries;
    svg.selectAll(".pref")
        .data(topo)
        .enter()
        .append("path")
        .attr("class", function(d) {
            return "pref pref" + pref[d.properties.name_local];
        })
        .attr("d", path);
});

各都道府県のパスにprefというクラスと、都道府県別のIDが付いたクラス(北海道ならpref1沖縄ならpref47)を付けておきます。
cssで白地図にします。

<style type="text/css">
.pref {
    fill: #fff;
    stroke: #aaa;
}
</style>

地図の横にカテゴリー名を表示して、そのテキストをマウスオーバーした時に、該当するカテゴリーの数値情報が地図上の色でわかるようにします。
数値が多い都道府県がより濃い赤になるようにしました。(255以上の値はみんな同じ色になりますが。)

svg.selectAll("text")
    .data(category)
    .enter()
    .append("text")
    .attr("class", "category-label")
    .attr("x", width - 160)
    .attr("y", function(d, i) {
        return i * 20 + 220;
    })
    .text(function(d) {
        return d.name;
    })
    .on("mouseover", function(d) {
        for (var key in d.data) {
            var color = 255 - d.data[key];
            if (color < 0) {
                color = 0;
            }
            d3.select(".pref" + key)
                .transition()
                .style("fill", "rgb(255, " + color + ", " + color + ")");
        }
        d3.select(this).style("fill", "#f66");
    })
    .on("mouseout", function(d) {
        for (var i = 1; i < 48; i++) {
            d3.select(".pref" + i)
                .transition()
                .style("fill", "#fff");
        }
        d3.select(this).style("fill", "black");
    });

『カテゴリー2』のテキストの上にマウスを置くと、このようになります。
スクリーンショット 2016-01-14 11.03.10.png

地図描くのもD3.jsを使えばそんなに難しくないな、と思いました。

ran
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away