はじめに
今更ですが、MapLibre GL JS の v4.0.0 が2月にリリースされました。変更点の中には、タイルをロードする際に実行する処理を追加することができる addProtocol
の破壊的変更が含まれています。
Changes
addProtocol
to be promise-based without the usage of callbacks and cancelable
MapLibre GL JS において、addProtocol
は PMTiles の消費などにおいて、他のウェブ地図ライブラリには代替できない機能となっていると認識しています。
そのため、今回の破壊的変更が、これまでのコードにおいてどのように影響を及ぼすのか、簡単に確認していきます。
参考:過去の関連記事
- addProtocol の解説記事(v3 の場合)
- PMTiles の解説記事
v3 と v4 での記述方法の違い
例として、単純に https プロトコルで fetch する custom://
というオリジナルプロトコルの設定方法を v3 と v4 で比較してみます。
maplibregl.addProtocol('custom', (params, callback) => {
console.log(params);
fetch(`https://${params.url.split("://")[1]}`)
.then(t => {
if (t.status == 200) {
t.arrayBuffer().then(arr => {
callback(null, arr, null, null);
});
} else {
callback(new Error(`Tile fetch error: ${t.statusText}`));
}
})
.catch(e => {
callback(new Error(e));
});
return { cancel: () => { } };
});
maplibregl.addProtocol('custom', async (params, abortController) => {
console.log(params);
const t = await fetch(`https://${params.url.split("://")[1]}`);
if (t.status == 200) {
const buffer = await t.arrayBuffer();
return {data: buffer}
} else {
throw new Error(`Tile fetch error: ${t.statusText}`);
}
});
変更点として、v3 の場合は、引数に設定した callback へ、変換したタイルデータを渡していましたが、v4 の場合は、Promise の履行結果としてタイルデータが渡されるようになっています。
なお、ベクトルタイル(pbf)の場合ですが、params の中身の主となる部分(タイルの URL やデータの type )の形式は変更ないようです。
{
"url": "custom://localhost/xyz/vector/13/7275/3227.pbf",
"type": "arrayBuffer"
}
PMTiles の消費方法
PMTiles は、一つのファイルの中にタイルデータ一式が格納されており、HTTP 範囲リクエストにより、目的のタイルを取り出します。
MapLibre GL JS 単独で PMTiles へ対応しているわけではなく、別途ライブラリが必要です。PMTiles レポジトリの参照実装/PMTiles package が利用されることが多いと感じています。
PMTiles package は v3.0.1 から MapLibre GL JS v4.x へ対応しているようです。以下のように MapLibre GL JS v4.1 と PMTiles package v3.0 の組み合わせで、特にコードを変更することもなく PMTiles を読み込めることを確認しました。
<script src='https://unpkg.com/maplibre-gl@4.1/dist/maplibre-gl.js'></script>
<link href='https://unpkg.com/maplibre-gl@4.1/dist/maplibre-gl.css' rel='stylesheet' />
<script src='https://unpkg.com/pmtiles@3.0/dist/pmtiles.js'></script>
let protocol = new pmtiles.Protocol();
maplibregl.addProtocol("pmtiles", protocol.tile);
複数の PMTiles を読み込む方法
以前の記事で複数の PMTiles を addProtocol を利用して読み込む方法を検討しました。
こちらも改めて試してみましたが、以下の記述のまま変更なしで対応できそうです。
let protocol = new pmtiles.Protocol();
const urlConvert = (url) => {
// convert url
// ここに URL の変換プログラムを記載
return url;
}
const myProtocol = (param, callback) => {
console.log(param);
// URL を変換
if(param.type != "json"){
param.url = urlConvert(param.url);
}
return protocol.tile(param, callback);
}
maplibregl.addProtocol("multi-pmtiles", myProtocol);
ただし、myProtocol()
へ渡す2つ目の引数名は、 callback ではなく、abortController と書き直した方が良いかもしれません。
おわりに
MapLibre GL JS も v4 まで開発が進みました。開発者の皆様に敬意を表します。PMTiles の利用も広がっている中、今回の破壊的変更で PMTiles の利用に影響が出るかと少し心配しましたが、特に大きな修正もなく、対応できそうで良かったです(PMTiles package 側の対応にも感謝です)。
今回の変更で、パフォーマンスへどの程度影響が出るかどうかは把握していません。今後、機会があれば、検証できるといいなと思っています。