🚀

Mapbox Newsletter WEEKLY TIPSの解説 -「リアルタイムデータを追加」

2023/09/07に公開

はじめに

この記事は、先日配信されたMapbox NewsletterのWEEKLY TIPSで紹介されていた「リアルタイムデータを追加」についての解説です。このサンプルでは国際宇宙ステーションの現在位置を2秒に1回取得し、地図上に現在位置を表示しています。また、Newsletterの購読はこちらからお申し込みいただけます。

コードを確認

まずExamplesのコードを見に行きましょう。

日本語サイト

英語サイト

基本的に同じコードですが、英語版はスタイルがMapbox Streets v12にアップグレードされているのでこちらを使用します。Mapbox Streets v11ではデフォルトのプロジェクションがWebメルカトルであるのに対し、Mapbox Streets v12ではGlobe(3D表示された地球)なので、印象がかなり異なります。また、ロケットのアイコンも変更されています。

HTML/CSS

まずHTMLを見ていきましょう。

以下は地図を表示するエレメントです。

<div id="map"></div>

Mapの作成

次にJavaScriptのコードを見ていきます。以下のコードはいつも通り、Mapオブジェクトを作成しています。containerで地図を表示するHTMLエレメントのidを指定します。

const map = new mapboxgl.Map({
  container: 'map',
  // Choose from Mapbox's core styles, or make your own style with Mapbox Studio
  style: 'mapbox://styles/mapbox/streets-v12',
  zoom: 1.5
});

コールバック

ソースおよびレイヤーの追加はloadイベントのコールバックの中で行います。また、コールバックの中でfetchによるデータ取得を行う関係上、asyncとしています。

map.on('load', async () => {/*ここ*/});

国際宇宙ステーションの位置の取得

getLocationという関数を定義し、その中で位置情報を取得しています。具体的にはhttps://api.wheretheiss.at/v1/satellites/25544というURLからfetchでデータを取得しています。レスポンスからlatitudelongitudeを取得しmap.flyToでカメラをその座標に移動させます。さらに、現在位置を座標とするポイントデータを含むGeoJSONを返しています。

async function getLocation(updateSource) {
  // Make a GET request to the API and return the location of the ISS.
  try {
    const response = await fetch(
      'https://api.wheretheiss.at/v1/satellites/25544',
      { method: 'GET' }
    );
    const { latitude, longitude } = await response.json();
    // Fly the map to the location.
    map.flyTo({
      center: [longitude, latitude],
      speed: 0.5
    });
    // Return the location of the ISS as GeoJSON.
    return {
      'type': 'FeatureCollection',
      'features': [
        {
          'type': 'Feature',
          'geometry': {
            'type': 'Point',
            'coordinates': [longitude, latitude]
          }
        }
      ]
    };
  } catch (err) {
    // If the updateSource interval is defined, clear the interval to stop updating the source.
    if (updateSource) clearInterval(updateSource);
    throw new Error(err);
  }
}

ソースの追加

getLocationの戻り値は国際宇宙ステーションの位置を表すGeoJSONだったので、それをそのままaddSourcedataとして使用しています。

// Get the initial location of the International Space Station (ISS).
const geojson = await getLocation();
// Add the ISS location as a source.
map.addSource('iss', {
  type: 'geojson',
  data: geojson
});

レイヤーの追加

先程追加したissをソースとするシンボルレイヤーを追加します。ロケットのアイコンを使用しています。

// Add the rocket symbol layer to the map.
map.addLayer({
  'id': 'iss',
  'type': 'symbol',
  'source': 'iss',
  'layout': {
    // This icon is a part of the Mapbox Streets style.
    // To view all images available in a Mapbox style, open
    // the style in Mapbox Studio and click the "Images" tab.
    // To add a new image to the style at runtime see
    // https://docs.mapbox.com/mapbox-gl-js/example/add-image/
    'icon-image': 'rocket'
  }
});

更新

国際宇宙ステーションの位置を更新するため、setIntervalで2秒ごとにgetLocationを呼んでいます。位置情報はsetDataを用いて更新します。

// Update the source from the API every 2 seconds.
const updateSource = setInterval(async () => {
  const geojson = await getLocation(updateSource);
  map.getSource('iss').setData(geojson);
}, 2000);

まとめ

このサンプルのポイントは、定期的にデータを取得してsetDataでソースのデータを更新する部分でした。以下で解説しているサンプルもsetDataの使い方に関するものなので、合わせてご参照ください。

おまけ

軌跡も描くようにしてみました。元のコードを最大限残すように記述しているので、若干冗長なコードになっています。

GitHubで編集を提案
マップボックス・ジャパン合同会社

Discussion