Skip to content

Update a Feature in Realtime

Simulate real-time data updates by periodically updating a GeoJSON source with setData().

Updating every second...

Real-time Update Pattern

javascript
// 1. Add a GeoJSON source
map.addSource('vehicle', {
  type: 'geojson',
  data: {
    type: 'Feature',
    geometry: { type: 'Point', coordinates: [lng, lat] },
    properties: {}
  }
});

map.addLayer({
  id: 'vehicle',
  type: 'circle',
  source: 'vehicle',
  paint: { 'circle-radius': 10, 'circle-color': '#3b82f6' }
});

// 2. Update position on an interval (or WebSocket message)
setInterval(() => {
  const { lng, lat } = getLatestPosition(); // your data source

  map.getSource('vehicle').setData({
    type: 'Feature',
    geometry: { type: 'Point', coordinates: [lng, lat] },
    properties: {}
  });
}, 1000);

With WebSocket (Real Production Pattern)

javascript
const ws = new WebSocket('wss://your-api.com/vehicles');

ws.onmessage = (event) => {
  const { id, lng, lat, speed } = JSON.parse(event.data);

  map.getSource('vehicles').setData({
    type: 'FeatureCollection',
    features: [{ type: 'Feature', geometry: { type: 'Point', coordinates: [lng, lat] }, properties: { id, speed } }]
  });
};

Complete Example

html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link href="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.css" rel="stylesheet" />
    <script src="https://cdn.mapmetrics-atlas.net/versions/latest/mapmetrics-gl.js"></script>
    <style>#map { height: 500px; width: 100%; }</style>
  </head>
  <body>
    <div id="map"></div>
    <script>
      const map = new mapmetricsgl.Map({ container: 'map', style: '<StyleFile_URL_with_Token>', center: [0, 20], zoom: 1.5 });
      map.on('load', () => {
        map.addSource('point', { type: 'geojson', data: { type: 'Feature', geometry: { type: 'Point', coordinates: [0, 20] } } });
        map.addLayer({ id: 'point', type: 'circle', source: 'point', paint: { 'circle-radius': 10, 'circle-color': '#3b82f6', 'circle-stroke-width': 3, 'circle-stroke-color': '#fff' } });

        let t = 0;
        setInterval(() => {
          t += 0.02;
          map.getSource('point').setData({
            type: 'Feature',
            geometry: { type: 'Point', coordinates: [(t * 15) % 360 - 180, Math.sin(t * 0.5) * 40] }
          });
        }, 200);
      });
    </script>
  </body>
</html>
jsx
import React, { useEffect, useRef } from 'react';
import mapmetricsgl from '@mapmetrics/mapmetrics-gl';
import '@mapmetrics/mapmetrics-gl/dist/mapmetrics-gl.css';

const RealtimeUpdate = () => {
  const mapContainer = useRef(null);
  const map = useRef(null);

  useEffect(() => {
    if (map.current) return;
    map.current = new mapmetricsgl.Map({ container: mapContainer.current, style: '<StyleFile_URL_with_Token>', center: [0, 20], zoom: 1.5 });

    let t = 0;
    let intervalId;

    map.current.on('load', () => {
      map.current.addSource('point', { type: 'geojson', data: { type: 'Feature', geometry: { type: 'Point', coordinates: [0, 20] } } });
      map.current.addLayer({ id: 'point', type: 'circle', source: 'point', paint: { 'circle-radius': 10, 'circle-color': '#3b82f6', 'circle-stroke-width': 3, 'circle-stroke-color': '#fff' } });

      intervalId = setInterval(() => {
        t += 0.02;
        map.current?.getSource('point')?.setData({
          type: 'Feature',
          geometry: { type: 'Point', coordinates: [(t * 15) % 360 - 180, Math.sin(t * 0.5) * 40] }
        });
      }, 200);
    });

    return () => { clearInterval(intervalId); map.current?.remove(); map.current = null; };
  }, []);

  return <div ref={mapContainer} style={{ height: '500px', width: '100%' }} />;
};

export default RealtimeUpdate;

For more information, visit the MapMetrics GitHub repository.