I am working from this update feature in realtime from Mapbox GL JS (https://docs.mapbox.com/mapbox-gl-js/example/live-update-feature/) and have successfully recreated it in my react app (see large code block below). Context: I am animating a bike route on my map.
What I am trying to accomplish: I would like to have a leading beacon (circle) to better show position as the line is animated.
What I have attempted: I successfully adding a second layer that is a circle but it adds [or plots] a circle for each data point along the entirety of the route.
Here is that specific Layer code (you will also see it in the full code below):
map.addLayer({
'id': 'beacon',
'type': 'circle',
'source': 'trace',
'paint': {
'circle-radius': 5,
'circle-color': 'white',
'circle-stroke-color': 'black',
'circle-stroke-width': 0.5
}
});
My questions:
- Is adding the circle element as a Layer the first step?
- How or where in the code can I state that only the leading data point should be plotted as a circle?
- If there is a common javascript function/method to accomplish this, could you please provide the correct language for it so I can continue to research with more effective results?
My code is basically the same as is used in the example provided. Again, This code works but it does not achieve my goal of only showing the leading circle -- rather it shows all plotted data points as a circle.
const Component = () => {
const mapContainerRef= useRef(null);
useEffect(() => {
const map = new mapboxgl.Map({
container: mapContainerRef.current,
style: 'mapbox://styles/mapbox/satellite-v9',
projection: 'mercator'
});
map.on('load', async () => {
// We fetch the JSON here so that we can parse and use it separately
// from GL JS's use in the added source.
const response = await fetch("../mydata.geojson");
//parsing the json
const data = await response.json();
// save full coordinate list for later
const coordinates = data.features[0].geometry.coordinates;
console.log(coordinates);
// start by showing just the first coordinate
data.features[0].geometry.coordinates = [coordinates[0]];
// add it to the map
map.addSource('trace', { type: 'geojson', data: data });
map.addLayer({
'id': 'trace',
'type': 'line',
'source': 'trace',
'paint': {
'line-color': '#000000',//'#F55DE1',
'line-opacity': 0.5,
'line-width': 8
}
});
map.addLayer({
'id': 'beacon',
'type': 'circle',
'source': 'trace',
'paint': {
'circle-radius': 5,
'circle-color': 'white',
'circle-stroke-color': 'black',
'circle-stroke-width': 0.5
}
});
// setup the viewport
map.jumpTo({
'center': coordinates[0],
'zoom': 14
});
//map.setPitch(30);
// on a regular basis, add more coordinates from the saved list and update the map
let i = 0;
console.log(coordinates.length);
const timer = setInterval(() => {
if (i < coordinates.length) {
data.features[0].geometry.coordinates.push(coordinates[i]);
map.getSource('trace').setData(data);
map.panTo(coordinates[i]); //pans to each coordinate area
i++;
} else {
window.clearInterval(timer);
}
}, 17.5);
});
return () => map.remove();
}, []);
return (
<div className="map-container" ref={mapContainerRef} style={{width:'100%', height:'100vh'}}/>
)
};
export default Component;
Edited several times to enhance post context.