Leafletでもうちょい天気図ぽいプロット(矢羽根と文字群(追記:+天気記号))


これは何ですか

これからは地図はなんでもWebGISでやりましょうということで、Leafletで地理院地図をベースマップにして気象データを描くというのをいろいろやっています。そのひとつが観測報プロット(さきのQiita記事)です。

とりあえず矢羽根はあらかじめ描画しておいた画像を Icon にして Marker を立てることができます。ついで雲量と矢羽根を併記するだけならば、Icon には iconUrl と shadowUrl の2つの画像が持てますから、目的外使用とはおもうけれどあらかじめ描画しておいた雲量記号を入れることができます。ここまでがとりあえず現状実現できたこと(2020-01-14現在)。

でも、ほんとは数字と記号てんこ盛りにしたいんですよね。地上の例:


(図は気象庁ホームページより)

まあここまでやらないにしても、気象的実用の観点からは、地上だったらせめて現在天気と気温くらいは、高層だったら気温と露点温度くらいは併記したい。

どうやるか。

DivIconは使えるんじゃないか

Leafletのリファレンスを眺めていると DivIcon という怪しいクラスがあります。任意のHTML片div要素を Marker に指定できるのです。
これを使えそうな気がしますね。

つまり、風(img 64x64)、雲量(img 16x16)、気温(div 最長5文字)、および露点(div 最長5文字)または現在天気(img おそらく24x24以上は必要)を重ね書きした div を DivIcon に入れればできるかな?

CSS の復習

  • HTML要素内のHTML要素の位置は、普通は左から右に流れるように配置されます(フロー)が、 position: absolute; を指定すると親要素からの絶対位置を topleft 等で指定するようになります (cf: MDN, tohoho)
  • img は大きさが知れているので同じ値を widthheight に指定すればよいですが、文字列の寸法と絶対位置を指定できるか。さしあたり、font-size, line-height あたりを指定するのか。
  • letter-spacing は変えても仕方がなさそう。letter-spacing: 1px; は普通より1ピクセル余計に隙間をあけるというだけで全体幅が限定できるものではありません。
  • そもそも 1px の幅が実装依存らしい。インチ表示との換算も、W3C は 90 dpi だというし、MDN は 96 dpi だというからたぶん firefox はそうなのでしょうかねし、定まりはないようです。

高層の例で実験

まだ現在天気記号を作っていないので高層からやってみます。実際の気象庁の高層天気図をみると、地上と異なり、気温は右上に、 露点温度 (訂正:湿数=気温マイナス露点、であった。2020-01-20T12Zから実施)は右下に書かれています(なお、WMOマニュアルには、少なくとも現在は、高層のプロットの規定はなくなっています)。これは高層天気図では西風が多いので、風矢羽根と数字がなるべくバッティングしないようにとの配慮でしょう。まあそれでもぶつかることはあるから、せめてもの抵抗で文字に影をつけてなんとか見えるようにしておきましょうか。

つまるところ、こんなふうにしてみればオリジナル画像と同じ64x64の箱に詰め込めるはずです。

<html>
<head>
<style type="text/css">
.stn { width: 64px; height: 64px;
  position: absolute; top: 150px; left: 100px; // この行は例示用。位置はleafletが決める
  border: 1px solid cyan; box-sizing: border-box; // この行はデバグ用 }
.wb { width: 64px; height: 64px; position: absolute; top: 0; left: 0; }
.ne { font-size: 10px; line-height: 10px;
  text-shadow: 1px 1px 0 #FFF;
  position: absolute; top: 20px; left: 32px; text-align: left; }
.se { font-size: 10px; line-height: 10px;
  text-shadow: 1px 1px 0 #FFF;
  position: absolute; bottom: 20px; left: 32px; text-align: left; }
</style>
<base href="https://toyoda-eizi.net/wxsymbols/"
</head>
<body>
<div class="stn">
<img class="wb" src="d27f70.png" />
<img class="wb" src="d4f70.png" />
<img class="wb" src="d11f70.png" />
<div class="ne">-77.7</div>
<div class="se">99.9</div>
</div>
</body>

やってみたらうまく動いたので https://github.com/etoyoda/bufrconv/commit/46b9eaadde3d6970f9851c03b7d7cc35e4db5dcd でコミットしました。デプロイ結果置き場 https://www.toyoda-eizi.net/nwp/p2/curr/?C=M;O=D では 2020-01-15T12Z 付プロットから使われる見込みです。なんとか間に合いました。

地上プロット:SVG天気記号の貼り込み

地上プロットでは、気温(左上)と現在天気(左下)が特に重要です。

  • 地点円の右側に数字をプロットして、字数によらず地点円から一定距離とするためには、 left: ではなく right: で位置づけします。あたりまえなのですがわからないと時間を取りました。
  • 天気記号は予め描画された画像を貼り込むわけですが、自分で描いている時間がなかったので OGC が配っている SVG 画像を使いました。気象庁ホームページの PNG 画像を切り抜いてもよいのですが、どのみちCC-BYですし、スクリプト書くのたるかったので。ところでCC-BYのクレジットは 20x20px の中には不可能なので、図郭右下にリンクで許してくれないかなあ…