Mapbox Newsletter WEEKLY TIPSの解説 -「フィーチャをリアルタイムで更新」
はじめに
この記事は、先日配信されたMapbox NewsletterのWEEKLY TIPSで紹介されていた「フィーチャをリアルタイムで更新」についての解説です。このサンプルではGeoJSONのデータを動的に変更し表示する方法を例示しています。また、Newsletterの購読はこちらからお申し込みいただけます。
コードを確認
まずExamplesのコードを見に行きましょう。
日本語サイト
英語サイト
タイトルが日本語訳されていること、Mapbox GL JSのバージョンが異なること以外は同じコードです。
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/satellite-v9',
zoom: 0
});
残りのコードはload
イベントのコールバック(map.on('load', async ()=>{})
)として実行されます。途中でGeoJSONのデータをfetch
で取得するためこのコールバックはasync
として宣言されています。
さて、通常GeoJSONをソースとして使用する場合はMap#addSource
の引数にURLとして直接指定することが多いです。それに対し、このサンプルではGeoJSONを一度fetch
で取得します。これは動的にデータを更新するというデモをする関係上、まず全データのGeoJSONを取得し、そのあと少しずつソースに追加していくためです。
const response = await fetch(
'https://docs.mapbox.com/mapbox-gl-js/assets/hike.geojson'
);
const data = await response.json();
GeoJSONの中身を確認します。LineStringが一つだけ入っています。
そしてcoordinates
にLineStringの座標を代入しています。データとしては[経度,緯度]
が配列に入ったものです。正確には参照が代入されます。
// save full coordinate list for later
const coordinates = data.features[0].geometry.coordinates;
data
をソース用のデータとして代用すべく、1つ目の座標だけを含む新しい配列を作成してその参照がcoordinates
に代入されます。
// start by showing just the first coordinate
data.features[0].geometry.coordinates = [coordinates[0]];
そして、その1つ目の座標だけを含むGeoJSON(data
)をソースとして登録(addSource
)し、Lineレイヤーを作成します。
// add it to the map
map.addSource('trace', { type: 'geojson', data: data });
map.addLayer({
'id': 'trace',
'type': 'line',
'source': 'trace',
'paint': {
'line-color': 'yellow',
'line-opacity': 0.75,
'line-width': 5
}
});
カメラの中心を1つ目の座標に移動させ、ズームを14、ピッチを30に設定します。
// setup the viewport
map.jumpTo({ 'center': coordinates[0], 'zoom': 14 });
map.setPitch(30);
アニメーションさせるためにsetInterval
で定期的に更新処理を実行します。if (i < coordinates.length)
により、元の座標データすべての点が表示されるまで処理が行われます。
data.features[0].geometry.coordinates.push(coordinates[i])
はi
番目の座標をデータの末尾に追加します。map.getSource('trace').setData(data)
でソースを更新します。データを更新してもsetData
を呼ばないとソースは更新されないので注意が必要です。そして、map.panTo(coordinates[i])
でカメラをi
番目の座標に移動させます。
// on a regular basis, add more coordinates from the saved list and update the map
let i = 0;
const timer = setInterval(() => {
if (i < coordinates.length) {
data.features[0].geometry.coordinates.push(coordinates[i]);
map.getSource('trace').setData(data);
map.panTo(coordinates[i]);
i++;
} else {
window.clearInterval(timer);
}
}, 10);
まとめ
データが更新されるたびにsetData
で更新するところがポイントでした。移動体の座標データを定期的に取得し、その軌跡を描くといった応用が考えられますね。
Discussion