search
LoginSignup
0
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

Mapbox Advent Calendar 2020 Day 10

posted at

updated at

Map.loadImage は Promise 化するのが吉

これは小手先のテクニックです。

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 を使用して並列に読み込みを行い、全てが読み込み終わってから次の行へ進む、という事が容易にできます。

完全なコードはこちら

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
0
Help us understand the problem. What are the problem?