GASで日本地図を表示する


GAS(Google App Script) で日本地図を表示します。D3のバージョン違いで結構つまずいたので、2020年1月時点での下記バージョンでの例をまとめておきます。

  • d3.js v5.15.0
  • topojson v3.0.2

ツールのインストール

地図データを変換するために使うツールをインストールします。

$ brew install gdal node jq
$ npm i -g topojson json-to-js

地図データのダウンロード

地図データは元記事と同じ通り、Natural Earthから地図データをダウンロードします。

$ curl -#L http://www.naturalearthdata.com/http//www.naturalearthdata.com/download/10m/cultural/ne_10m_admin_1_states_provinces.zip | bsdtar -xf- -C .

日本地図データの GeoJSON を作成します。

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

同様に静岡県の修正をします。

$ cat pref.json | jq '.features[30].properties.name_local|="静岡県"' > pref2.json

次に TopoJSON を作成します。

$ geo2topo -p name -p name_local -p latitude -p longitude -o japan.json pref2.json

作成された japan.json を後の GAS で使いやすくするために、JavaScript のリテラルに変換します。

$ cat japan.json | json-to-js > japan.js

GASでHTMLを用意する

Google Drive を開き、Google Apps Script を新規作成します。

下記3つのファイルを追加します。

コード.gs
function doGet() {
  return HtmlService.createTemplateFromFile("index").evaluate();
}
index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script src="https://unpkg.com/topojson@3"></script>
  </head>
  <body>
    <div class="japan"></div>
    <script>
      var width = 960,
          height = 1160;
      var color = d3.scaleOrdinal(d3.schemeCategory10);
      var projection = d3.geoMercator()
        .center([135, 35])
        .scale(2400)
        .translate([width / 2, height / 2]);
      var path = d3.geoPath().projection(projection);
      var svg = d3.select(".japan").append("svg")
        .attr("width", width)
        .attr("height", height);
      var topoJapan = <?!= HtmlService.createHtmlOutputFromFile("topoJapan").getContent() ?>;
      var geoJapan = topojson.feature(topoJapan, topoJapan.objects.pref);
      svg.selectAll(".pref")
        .data(geoJapan.features)
        .enter()
        .append("path")
        .attr("stroke", "#999")
        .attr("fill", "none")
        .attr("d", path);
    </script>
  </body>
</html>

元記事では d3.json(...).then(...) を使っているが、GAS では XHR が使えないため、作成した japan.js をそのまま読み込ませている。

topoJapan.html
/* TODO: japan.js ファイルをコピー */

ここで、GAS ではすごく長い1行をレンダリングするために5分くらいかかってしまうので、絶対に japan.json を GAS に貼り付けてはいけない。(体験談)

ウェブに公開する

公開 > ウェブアプリケーションとして導入... をクリック

アクセスを全員にして、公開/更新をクリック。

実際のページはこちら
https://script.google.com/macros/s/AKfycbyhpbiK4wsFBwEI0uKT6iOctE9mK9f4-LxrpgRiLGnBb61nqA5o/exec

参考