Update a feature in realtime
With maplibre you can change an existing feature on your map in real-time by updating its data.
# begin by installing d3-fetchbun add d3-fetch @types/d3-fetch
import { createEffect, createSignal, on, onCleanup, type Component } from "solid-js";import { LineLayer, Maplibre, Source } from "solidjs-maplibre-gl";import "maplibre-gl/dist/maplibre-gl.css";import * as d3 from "d3-fetch";import type { FeatureCollection, Feature, LineString, Position } from "geojson";import type { LngLatLike } from "maplibre-gl";
// A feature with a LineString geometry and no propertiestype LineStringFeature = Feature<LineString, null>;
// Your feature collection of LineStrings, no properties neededtype LineStringFeatureCollection = { type: "FeatureCollection"; features: LineStringFeature[];};
type BaseFeatureCollection = Omit< FeatureCollection<LineString, null>, "features"> & { features: LineStringFeature[];};
const RouteFeat: Component = (props) => { const [geoData, setGeoData] = createSignal<BaseFeatureCollection | null>( null, ); const [map, setMap] = createSignal<maplibregl.Map>(); //reactive gotcha createEffect( on( map, async (currentMap) => { if (!currentMap) return; // We use D3 to fetch the JSON here so that we can parse and use it separately // from GL JS's use in the added source. You can use any request method (library // or otherwise) that you want. const data = (await d3.json( "https://maplibre.org/maplibre-gl-js/docs/assets/hike.geojson", )) as BaseFeatureCollection; // save full coordinate list for later const coordinates = data.features[0].geometry.coordinates; // start by showing just the first coordinate data.features[0].geometry.coordinates = [coordinates[0]]; // create a reference to the data for use in the src component setGeoData(data); // setup the viewport currentMap .jumpTo({ center: coordinates[0] as LngLatLike, zoom: 14 }) .setPitch(30); // 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]); const source = map()?.getSource("trace") as | maplibregl.GeoJSONSource | undefined; source?.setData(data); map()?.panTo(coordinates[i] as LngLatLike); i++; } else { clearInterval(timer); } }, 10); }, { defer: true }, ), ); return ( <Maplibre style={{ height: "55vh", "min-height": "300px", }} options={{ zoom: 0, style: "https://tiles.openfreemap.org/styles/liberty", }} onidle={(e) => { setMap(e.target); }} > <Source id="trace" source={{ type: "geojson", data: geoData() as FeatureCollection, }} > <LineLayer layer={{ paint: { "line-color": "#9b5b08ff", "line-opacity": 0.75, "line-width": 5, }, }} /> </Source> </Maplibre> );};
export default RouteFeat;