maplibre-gl-opacityをMapbox GL JSで使ってみる
はじめに
現在、Software Designで連載中の「位置情報エンジニアリングのすすめ」を毎月楽しく拝読しております。第6回「防災マップの作成① 浸水想定区域と避難所を可視化する」ではMapLibre GL JSを用いて地理情報を表示していました。記事にも記載されている通り、MapLibre GL JSはMapbox GL JSからフォークされた地図ライブラリなので、使い方は非常に似通っています。そこで、ここでは紙面で紹介されていたMapLibre GL JS用のプラグインであるmaplibre-gl-opacityをMapbox GL JSで使ってみようと思います。
maplibre-gl-opacityとは
maplibre-gl-opacityはMapLibre GL JS用のプラグインで、スタイル上のレイヤーの表示・非表示設定や不透明度の設定を行うことができます。作者様の解説記事は以下です。
maplibre-gl-opacityの使い方
maplibre-gl-opacityはIControlとして実装されています。そのため、以下のコードのようにOpacityControlをインスタンス化し、Map#addControlで地図上に表示します。
const opacity = new OpacityControl({
baseLayers: {
'tokyo-st-green': 'GREEN',
'tokyo-st-blue': 'BLUE',
},
overLayers: {
satellite: 'Satellite',
},
opacityControl: true,
});
map.addControl(opacity, 'top-left');
上記のコードで以下のようなコントロールが表示されます。baseLayersで指定したレイヤーは択一式のラジオボタン、overLayersで指定したレイヤーは複数選択可能なチェックボックスとして表示されます。また、opacityControlをtrueとすることでoverLayersの不透明度を設定するためのスライダーが表示されます。

maplibre-gl-opacityのコードを読む
IControlはMap#addControlのタイミングでonAdd関数が実行されます。つまり、IcontrolのエントリポイントはonAdd関数なので、ここからコードを読むと良いです。
_opacityControlAdd()関数が内部で呼ばれているようなので中を見ていきます。
baseLayersに関する処理
以下でbaseLayersに関する処理が行われています。baseLayersはキーがレイヤーIDなので、Object.keysでレイヤーIDの配列が取得されます。その配列に対してmapを作用させ、各レイヤーIDを引数として_radioButtonControlAdd関数を実行しています。
_radioButtonControlAddではラジオボタンを作成します。さらに、1つ目のレイヤーに対してはMap#setLayoutPropertyを使用し、visibilityプロパティをvisibleに、それ以外のレイヤーはnoneに設定しています。
さらに、ラジオボタン選択時に、選択されたレイヤーをvisibleにする処理が記述されています。
また、baseLayersの値はラベルとして利用されます。
overLayersに関する処理
以下でoverLayersに関する処理が行われています。overLayersもキーがレイヤーIDなので、Object.keysでレイヤーIDの配列が取得されます。その配列に対してmapを作用させ、各レイヤーIDを引数として_checkBoxControlAdd関数を実行しています。
_checkBoxControlAdd関数ではチェックボックスを作成します。さらに、全てのレイヤーを非表示状態にします。
また、チェックボックス選択時に表示・非表示を切り替える処理が記述されています。
opacityControlがtrueのときには_rangeControlAdd関数も実行されます。
_rangeControlAdd関数ではスライダーを作成し、スライダー変更時にMap#setPaintPropertyでraster-opacityを変更しています。
raster-opacityはラスターレイヤー専用のプロパティなので、opacityControlを使用する際にoverLayersに指定できるレイヤーはラスターレイヤーのみとなります。
maplibre-gl-opacityをMapbox GL JSで使う
上記ではmaplibre-gl-opacity内部で使用されるMapLibre GL JSの機能を見てきました。以下の表はMapLibre GL JSとMapbox GL JSの機能を比較です。これらの機能はMapbox GL JS v1.13.0以前に実装されたものなので、基本的に互換性があることが期待されます。
| MapLibre GL JS | Mapbox GL JS |
|---|---|
IControl |
IControl |
Map#addControl |
Map#addControl |
Map#setLayoutProperty |
Map#setLayoutProperty |
Map#setPaintProperty |
Map#setPaintProperty |
サンプル全体
まず今回作成したサンプルです。
import { Map } from 'mapbox-gl';
import 'mapbox-gl/dist/mapbox-gl.css';
// @ts-ignore
import OpacityControl from 'maplibre-gl-opacity';
import 'maplibre-gl-opacity/dist/maplibre-gl-opacity.css'
import tokyoSt from './tokyo_st.json'
const map = new Map({
accessToken: 'YOUR_MAPBOX_ACCESS_TOKEN',
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [139.768435, 35.681054],
zoom: 15,
});
map.on('style.load', () => {
map.addSource('tokyo-st', {
type: 'geojson',
data: tokyoSt as any,
});
map.addLayer({
'id': 'tokyo-st-green',
'type': 'fill',
'source': 'tokyo-st',
'paint': {
'fill-color': '#00ff00',
}
});
map.addLayer({
'id': 'tokyo-st-blue',
'type': 'fill',
'source': 'tokyo-st',
'paint': {
'fill-color': '#0000ff',
}
});
map.addSource('satellite', {
'type': 'raster',
'url': 'mapbox://mapbox.satellite',
});
map.addLayer({
'id': 'satellite',
'type': 'raster',
'source': 'satellite',
});
const opacity = new OpacityControl({
baseLayers: {
'tokyo-st-green': 'GREEN',
'tokyo-st-blue': 'BLUE',
},
overLayers: {
satellite: 'Satellite',
},
opacityControl: true,
});
map.addControl(opacity, 'top-left');
opacity._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group';
});
以下で各部分の動作を確認します。
地図の作成
以下ではMapをインスタンス化しています。
const map = new Map({
accessToken: 'YOUR_MAPBOX_ACCESS_TOKEN',
container: 'map',
style: 'mapbox://styles/mapbox/streets-v12',
center: [139.768435, 35.681054],
zoom: 15,
});
ソース・レイヤーの作成
ソース・レイヤーの作成はmap.on('style.load', () => { /* ここ */})の部分で行います。
以下は東京駅のポリゴンをGeoJSONから読み込んでいます。また、ポリゴンを緑色で塗りつぶしたtokyo-st-greenレイヤーとポリゴンを青色で塗りつぶしたtokyo-st-blueレイヤーを作成しています。これらのレイヤーはbaseLayersで使用します。
map.addSource('tokyo-st', {
type: 'geojson',
data: tokyoSt as any,
});
map.addLayer({
'id': 'tokyo-st-green',
'type': 'fill',
'source': 'tokyo-st',
'paint': {
'fill-color': '#00ff00',
}
});
map.addLayer({
'id': 'tokyo-st-blue',
'type': 'fill',
'source': 'tokyo-st',
'paint': {
'fill-color': '#0000ff',
}
});
以下はMapboxのSatellite Tilesetをソースとして使用します。また、このタイルセットはラスターなので、ラスターレイヤーとして追加します。このレイヤーはoverLayersで使用します。
map.addSource('satellite', {
'type': 'raster',
'url': 'mapbox://mapbox.satellite',
});
map.addLayer({
'id': 'satellite',
'type': 'raster',
'source': 'satellite',
});
maplibre-gl-opacityの作成
maplibre-gl-opacityの使い方で見た通り、OpacityControlをインスタンス化し、addControlします。
const opacity = new OpacityControl({
baseLayers: {
'tokyo-st-green': 'GREEN',
'tokyo-st-blue': 'BLUE',
},
overLayers: {
satellite: 'Satellite',
},
opacityControl: true,
});
map.addControl(opacity, 'top-left');
最後にちょっとしたハックです。Mapbox GL JSで使用する際に必要なクラス名の指定を行います。
opacity._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group';
この指定の背景は以下のとおりです。
maplibre-gl-opacityコントロールのHTMLエレメントに対し、maplibregl-ctrlおよびmaplibregl-ctrl-groupというクラスが割り当てられています。
これらのクラスは以下の様にMapLibre GL JSのCSSで定義されています。IControlで作成するコントロールに対してこのクラスを割り当てることで、いい感じに表示されます。
同様のクラスがMapbox GL JSでは以下のように定義されています。
そこで、Mapbox GL JSで使用する場合にはmaplibregl-ctrlをmapboxgl-ctrlに、 maplibregl-ctrl-groupをmapboxgl-ctrl-groupに変更する必要があります。
結果
以下のように表示されます。

デモは以下のサイトで試せます。
まとめ
ちょっとしたハックは必要でしたが、maplibre-gl-opacity(v1.6.0)がMapbox GL JS(v3.0.1)でも使用できることがわかりました。ただし、今後MapLibre GL JSの独自機能を使う変更が加えられたり、MapLibre Gl JSまたはMapbox GL GLの既存機能に破壊的変更があった場合には使用できなくなる可能性もあります。
OpacityControlの設定に関して、baseLayersという名称からベースマップとして表示するラスターレイヤーの使用がライブラリとしての期待値かもしれません。しかし、今回のような任意のレイヤーの表示の選択にも利用可能です。
また、紙面ではOpacityControlを2つ作成していましたが、一つはベースマップの選択用、もう一つは浸水想定区域の選択用として作成していると推察されます。一つのOpacityControlに対し、後者をoverLayersとして表示する使い方もあるかと思います。
おまけ
紙面で以下のような脚注がありました。
注5) MapLibre GL JSはv3から一部のプラグインが機能しない問題があるため、本連載では最新バージョンではなく動作が安定しているv2.4.0を使います。
https://github.com/maplibre/maplibre-gl-js/blob/main/CHANGELOG.md#potentially-breaking-changes
リンク先を確認するとPotentially breaking changesとして以下の項目があります。
⚠️ Remove deprecated mapboxgl- css classes (use maplibregl- instead) (#1575)
maplibre-gl-opacityはv1.5.0でクラスをmaplibregl-ctrl、maplibregl-ctrl-groupに変更しているので問題ないですが、Mapbox GL JS用に開発されたプラグインは使えなくなっていると考えられます。
Discussion