🏎️

Mapbox で点をスムースに移動させる

2 min read

Mapbox で移動する点を描く では、連続した点を単純に描画してみました。
が、パカパカ移動するので何だかつまらないしありきたりです。
なので、Uber アプリのようにもっとスムースにシンボルを移動させます。

完成形は↓です。

はじめに

で例が示されているので、これを改造します。

また、この機能を実現させるのに、turf.js という地理空間図形や座標の計算を行ってくれるライブラリを使用します。

index.js

処理の要点は2つです。

1.requestAnimationFrame を使ってフレーム毎に描画を行う
2. ルートの「開始点からnメートル進んだ点」を turf.js で計算する

移動する速度(km/h)はここでは固定とします。
requestAnimationFrame で描画のハンドラ関数を再帰で繰り返し呼び出し、前回の描画から今回までにかかった時間(ミリ秒)で何m進むのかを計算します。
進んだ距離を加算しておき、turf.js を使って「開始点から Nm 進んだ座標」を取得して、DataSource を更新→画面を更新します。

const waypoints = [
  [136.53890132904053,34.844644908488974],
  [136.54332160949704,34.840242190008105],
  // 中略 //
  [136.5387511253357,34.84480340196252]
];

// Symbol Layer
const symbolData = {
  'type': 'FeatureCollection',
  'features': []
};
map.on('load', function() {
  map.loadImage(
    'https://img.icons8.com/material/32/0000FF/marker--v1.png',
    (error, image) => {
      // 中略 //

      time = new Date().getTime();
      animate();
    }
  );
});

const line = turf.lineString(waypoints);
const lineLength = turf.length(line, { units: 'meters' });

const kph = 600; // 600km/h
let time = null;
let distance = 0;

function animate() {
  // 1フレームで移動する距離を算出
  const now = new Date().getTime();
  const offset = now - time;
  time = now;
  const movingInMeters = ((kph / 60 / 60 / 1000) * offset) * 1000;
  
  // 移動距離加算
  distance = distance + movingInMeters;

  // 移動した点を計算
  const options = {units: 'meters'};
  const movedPoint = turf.along(line, distance, options);

  // 更新
  symbolData.features.splice(0);
  symbolData.features.push({
    'type': 'Feature',
    'geometry': {
      'type': 'Point',
      'coordinates': movedPoint.geometry.coordinates
    }
  });
  const dataSource = map.getSource('point');
  dataSource.setData(symbolData);
  
  // repeat
  if (distance >= lineLength) {
  	distance = 0;
  }
        
  requestAnimationFrame(animate);
}

DEMO

時速600km の設定なので F1 よりも相当速いです。

See Also