これは小手先のテクニックです。
Add an icon to the map のように、Symbol Layer を表示するためには、アイコン画像を事前に Map.loadImage
し、さらに Map.addImage
で登録する必要があります(sprite を使わない場合)。
map.loadImage
は非同期の関数で、レスポンスは (error, image) => void
のコールバックで通知されるため、上記のサンプルプログラムもインデントが深く見づらくなっています。
ここを Promise 化してあげれば、最近の JavaScript 動作環境では await 構文を使用してすっきり書けます。
const loadImageAsPromise = (map, url) => {
return new Promise((resolve, reject) => {
map.loadImage(url, (error, image) => {
if (image != null) {
resolve(image);
} else {
reject(error);
}
});
});
};
map.once('load', async () => {
// Icons by https://icons8.com/
const images = await Promise.all([
loadImageAsPromise(map, 'https://img.icons8.com/material/48/FF0000/user-location--v1.png'),
loadImageAsPromise(map, 'https://img.icons8.com/material/48/FF00FF/car.png'),
loadImageAsPromise(map, 'https://img.icons8.com/material/48/0000FF/airplane-mode-on--v1.png'),
]);
map.addImage('human', images[0]);
map.addImage('car', images[1]);
map.addImage('airplane', images[2]);
map.addLayer({
'id': 'points',
'type': 'symbol',
'source': 'points',
'layout': {
'icon-image': [ 'get', 'icon' ],
}
});
});
loadImageAsPromise
という関数を定義しています。これはコールバックだった戻り値を Promise<画像データ>
にしたものです。
これを地図が読み込まれたイベントで await
で呼び出します。
さらに、画像を複数読み込む場合は、Promise.all
を使用して並列に読み込みを行い、全てが読み込み終わってから次の行へ進む、という事が容易にできます。