Отслеживание перемещения

В основе отслеживания перемещения в Mapbox GL JS лежит постоянное обновление источника данных и синхронизация состояния карты с поступающими координатами. Основные сценарии включают отображение текущего положения объекта, построение траектории движения, управление камерой карты и плавную анимацию перемещения маркера.


Источник геоданных и структура обновления

Ключевым элементом становится GeoJSON source, который динамически изменяет координаты точки или линии. Структура обычно строится вокруг объекта Feature:

const geojsonSource = {
  type: "geojson",
  data: {
    type: "FeatureCollection",
    features: [
      {
        type: "Feature",
        geometry: {
          type: "Point",
          coordinates: [0, 0]
        }
      }
    ]
  }
};

Добавление источника на карту:

map.addSource("tracked-point", geojsonSource);

Дальнейшее обновление координат выполняется через setData, что обеспечивает полную перерисовку связанного слоя:

map.getSource("tracked-point").setData({
  type: "FeatureCollection",
  features: [
    {
      type: "Feature",
      geometry: {
        type: "Point",
        coordinates: [lng, lat]
      }
    }
  ]
});

Получение координат устройства

Для получения данных о перемещении используется браузерный API геолокации:

navigator.geolocation.watchPosition(
  (position) => {
    const lng = position.coords.longitude;
    const lat = position.coords.latitude;
  },
  (error) => {
    console.error(error);
  },
  {
    enableHighAccuracy: true,
    maximumAge: 0,
    timeout: 5000
  }
);

Метод watchPosition обеспечивает потоковое обновление координат, что позволяет реализовать непрерывное отслеживание движения.


Отображение маркера текущего положения

Для визуализации перемещения часто используется Marker, синхронизируемый с координатами:

const marker = new mapboxgl.Marker()
  .setLngLat([0, 0])
  .addTo(map);

Обновление позиции маркера:

marker.setLngLat([lng, lat]);

При высокочастотных обновлениях предпочтительно использовать оптимизацию через ограничение частоты перерисовки, чтобы избежать перегрузки рендеринга.


Построение траектории движения

Для отображения маршрута используется линия LineString, которая расширяется при поступлении новых координат.

const route = {
  type: "Feature",
  geometry: {
    type: "LineString",
    coordinates: []
  }
};

Обновление траектории:

route.geometry.coordinates.push([lng, lat]);

map.getSource("route").setData(route);

Такой подход формирует непрерывную линию перемещения объекта на карте.


Плавная анимация движения

Резкие скачки координат устраняются через интерполяцию. Базовый подход основан на requestAnimationFrame:

function animate(from, to, progress) {
  return [
    from[0] + (to[0] - from[0]) * progress,
    from[1] + (to[1] - from[1]) * progress
  ];
}

Цикл анимации:

let start;
const duration = 1000;

function step(timestamp) {
  if (!start) start = timestamp;

  const progress = Math.min((timestamp - start) / duration, 1);

  const current = animate(prevCoords, nextCoords, progress);

  marker.setLngLat(current);

  if (progress < 1) {
    requestAnimationFrame(step);
  }
}

Этот механизм сглаживает перемещение и делает визуализацию более стабильной.


Автоследование камеры

Для удержания объекта в центре экрана используется изменение центра карты:

map.setCenter([lng, lat]);

При необходимости добавляется плавность:

map.easeTo({
  center: [lng, lat],
  duration: 500
});

Более продвинутый вариант включает управление наклоном и масштабом:

map.easeTo({
  center: [lng, lat],
  zoom: 15,
  bearing: heading,
  pitch: 45,
  duration: 700
});

Отслеживание направления движения

Направление вычисляется на основе разницы между предыдущей и текущей точками:

const dx = lng2 - lng1;
const dy = lat2 - lat1;

const heading = Math.atan2(dx, dy) * (180 / Math.PI);

Полученное значение используется для поворота карты или иконки маркера.


Использование GeolocateControl

Встроенный компонент Mapbox GL JS предоставляет готовую реализацию трекинга:

const geolocate = new mapboxgl.GeolocateControl({
  positionOptions: {
    enableHighAccuracy: true
  },
  trackUserLocation: true
});

map.addControl(geolocate);

Контрол автоматически управляет обновлением координат и отображением позиции пользователя, включая направление движения.


Синхронизация нескольких объектов

При отслеживании нескольких объектов используется структура FeatureCollection, где каждый объект имеет уникальный идентификатор:

const collection = {
  type: "FeatureCollection",
  features: [
    {
      type: "Feature",
      properties: { id: 1 },
      geometry: { type: "Point", coordinates: [lng1, lat1] }
    },
    {
      type: "Feature",
      properties: { id: 2 },
      geometry: { type: "Point", coordinates: [lng2, lat2] }
    }
  ]
};

Обновление выполняется целиком через setData, что гарантирует консистентность отображения.


Оптимизация частых обновлений

При высокой частоте входящих координат используется буферизация:

  • накопление последних координат
  • ограничение частоты setData
  • использование requestAnimationFrame вместо прямых обновлений
  • разделение логики получения данных и рендеринга

Такой подход снижает нагрузку на WebGL-рендерер карты.


Работа с углами обзора и 3D-сценой

В 3D-режиме движение объекта дополняется управлением перспективой:

map.setPitch(60);
map.setBearing(heading);

Комбинация наклона и поворота позволяет визуально согласовать движение объекта с направлением камеры, создавая эффект навигации в пространстве.


Интеграция потоковых данных

При подключении внешних источников координат (WebSocket, SSE) обновление источников карты синхронизируется с входящим потоком:

socket.onmess age = (event) => {
  const data = JSON.parse(event.data);

  map.getSource("tracked-point").setData(data);
};

Это позволяет отображать движение объектов в реальном времени без промежуточных задержек на стороне клиента.


Управление состоянием движения

При построении системы трекинга важно разделять:

  • текущую позицию
  • последнюю стабильную позицию
  • прогнозируемую траекторию
  • визуализированную траекторию

Такая модель обеспечивает контроль над визуальной непрерывностью даже при потере пакетов данных или задержках сети.