地震が起きたときの地図上に震度が表示されるやつが気になったから作ってみた


皆さんは、地震が起きたとき何をしますか?

  • Twitterで実況する
  • テレビのチャンネルをNHKに変える
  • ラジオを付ける

など、色々あるかと思います。
私は、Twitterで特務機関NERV防災のアカウントをチェックします。

もちろん身の安全を確保するのが最優先です。

Twitterでは特務機関NERVの他にYahooやらtenki.jpやらウェザーニューズなどが地震情報を発信しています。
このようなアカウントで私は毎回、下のような画像をどうやって生成するのが凄く気になっていました。

調べてみた

この画像は、震度分布図と呼ぶみたいです。
似たようなものを作っていないかと、Qiitaで調べたところ以下のような記事がありました。

気象庁防災情報XMLとD3.jsを使って地震の震度分布図を作る
https://qiita.com/icchi_h/items/bbf563e1a7acec97a0e0

この記事によると、D3.jsを使用すればできるという内容が書かれています。
作ろうと思えば作れるということがわかったので、作ってみました。

作ってみた

記事には具体的な実装方法やソースコードはないため、node上でD3.jsを使用して試行錯誤しました。

D3.jsはバージョンが上がるごとに機能が頻繁に変更されているらしく、ネット上のソースコードが動かないなどがあり大変でした。

最終的にソースコードは以下のようになりました。

const d3 = Object.assign({}, require('d3'), require('d3-queue'));
const fs = require('fs');
const simplify = require('simplify-geojson')

...

// 日本地図を読み込む
const q = d3.queue()
    .defer(fs.readFile, map);

q.awaitAll((err, files) => {
    if (err) throw err;
    var data = JSON.parse(files);
    // 地図を少し単純化する
    data = simplify(data, resolution);


    // 地図のどこを描画するか
    var aProjection = d3.geoMercator()
        .center(center)
        .translate([width / 2, height / 2])
        .scale(def_scale * _scale);

    var geoPath = d3.geoPath()
        .projection(aProjection);

    // SVGの設定
    var svg = d3.select(document.body)
        .append('svg')
        .attr('xmlns', 'http://www.w3.org/2000/svg')
        .attr('width', width)
        .attr('height', height)
        .attr('xmin', aProjection.invert([0, 0])[0])
        .attr('xmax', aProjection.invert([width, height])[0])
        .attr('ymin', aProjection.invert([width, height])[1])
        .attr('ymax', aProjection.invert([0, 0])[1])
        .attr('scale', aProjection.scale())
        .attr('encoding', 'utf-8')
        .style('background-color', sea_color);

    // 地図を描画させる
    svg.append('path')
        .datum(data)
        .attr('d', geoPath)
        .attr('stroke-width', 1)
        .attr('stroke-linejoin', 'round')
        .attr('stroke-linecap', 'round')
        .style('fill', land_color)
        .style('stroke', stroke_color);

    ...
}

詳しいソースコードはGithubに上げてあります。
https://github.com/earthquake-alert/map-draw

最終的にはこのような画像を生成できるようになりました。

個人的に、

  • 背景色、震度色など様々な設定をjsonファイルで簡単に変更できる
  • 画像の中心を震源地ではなく、すべての震度の平均値

を工夫しました。

ちなみに、明るい色バージョンも生成するとこのようになります。

作ってみた感想

分布図生成→png画像に変換というすべての処理をする場合、最大3秒ほどかかってしまいます。
1秒以内で処理を完了していち早く情報を発信できる特務機関NERV防災はものすごいんだなと改めて感じました。

最後に

詳しく知りたいときはやはり自分で作ってみるのがいいですね!