[Leaflet]レイヤを乗算で重ねる(タイルレイヤの乗算合成)

このBlogとかでLeafletを使ったコンテンツを作るようになってから数年経って念願だった、タイルレイヤを乗算合成することが出来ましたので、ここに実装方法をメモしてこきます。これまで何度となく「Leaflet 乗算」で検索したのですが、最上位に表示されたのはこのBlogの「(OpenLayersは)乗算でレイヤを重ねられたのは良かったのですけど・・・」という部分で絶望的な気分になっていました。

Leaflet 乗算での検索結果(2021.5.9)

ところが、AMeDAS観測による複数の気象要素とレーダー画像を一枚の地図で見れるページを作っているなかで、Leaflet上で表示される地物はすべてDivタグの中に含まれていること、CSSにレイヤの合成モードを指定するプロパティ(mix-blend-mode)があることなどが分かってきて、最終的に乗算合成することが出来るようになったのでした。

さて、前置きはこの辺にして本題に入ります。

Leafletでレイヤを乗算合成したい場合、下記の手順で実装できました。
なお、CSSのmix-blend-modeがIEでは使えないそうなので、閲覧環境によっては無効となります。

  1. マップ(map)からペイン(pane)を作成し、返り値(HTMLElement)を保存しておく。
  2. 1で保存したHTMLElementのStyleを変更する。
  3. 乗算合成したいレイヤに1で作成したペインを指定する。

早速、サンプルソースを載せてみます。

<div id="leafletmap">
<script>
    //地図を生成(初期表示の中心座標,ズームレベル,レイヤなどをオプションで設定)
    let map = L.map('leafletmap', {center: [35.885870,139.536618], zoom: 15});
    //
    //ペイン作成→乗算合成
	let pnMulti = map.createPane("Multiply");
	pnMulti.style.mixBlendMode = "multiply";
	//
    //切り替え可能とするタイルレイヤを生成(タイルURL,ズーム範囲,著作権表示などをオプションで設定)
    let std = L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
        minZoom: 5, maxZoom: 18, 
        attribution: "地理院タイル"
        });
    let pal = L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png', {
        minZoom: 5, maxZoom: 18, 
        attribution: "地理院タイル"
        });
    let blk = L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/blank/{z}/{x}/{y}.png', {
        minZoom: 5, maxZoom: 14, 
        attribution: "地理院タイル"
        });
    let ort = L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/ort/{z}/{x}/{y}.jpg', {
        minZoom: 5, maxZoom: 18, 
        attribution: "地理院タイル"
        });
    let rapid = L.tileLayer('https://habs.dc.affrc.go.jp/rapid16/{z}/{x}/{y}.png', {
        tms: true, opacity: 1.0,
        minZoom: 8, maxZoom: 16, 
        attribution: "迅速測図(農業環境技術研究所)"
        });
    let flood2019 = L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/20191012typhoon19_arakawa_1014dansaizu/{z}/{x}/{y}.png', {
        minZoom: 5, maxZoom: 15, opacity: 1.0,
        pane: pnMulti,
        attribution: "地理院タイル"
        });
    // 
    //最初に表示するレイヤ
    map.addLayer(pal);
    map.addLayer(flood2019);
    // 
    //レイヤコントロールに切り替え可能とするレイヤを追加
    L.control.layers({
        '地理院タイル(標準地図)': std,
        '地理院タイル(淡色地図)': pal,
        '地理院タイル(写真)': ort,
        '明治期迅速測図': rapid
        }, 
        {
        '浸水判読図(令和元年台風第19号)': flood2019
        }, {collapsed: true}).addTo(map);
    //
    //スケールコントロールを追加(オプションはフィート単位を非表示)
    L.control.scale({imperial: false}).addTo(map);
</script>
</div>

まず、7行目で「Multiply」という名前のペインを作成(名前は任意)するとともに、帰り値を「pnMulti」という変数に保存しています。
次に、8行目でpnMultiのスタイルを乗算にしています。pnMultiはHTMLElementオブジェクトなので、「pnMulti.style.~」で合成モード以外のスタイルも当然ながら指定(変更)出来ます。例えばz-indexでレイヤの表示順を指定することも出来ます(参考:Leafletでのデフォルトのz-index(Leaflet公式サイト))。
最後に、36行目で乗算合成したいレイヤのペインに「pnMulti」を指定することで、乗算合成を有効にしています。

[R]相関を持つ乱数ペア

モンテカルロシミュレーションとかで、相関を持つ乱数ペアを作りたい場合があるかと思います。ネットを調べると色々と記事が出てくるので作り方の詳細...