Visualize dynamic data using mapbox - javascript

I am following this example to visualize data on a map using mapbox. I use the following code:
<script> mapboxgl.accessToken = 'ACCESS_TOKEN; var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
zoom: 12,
center: [-122.447303, 37.753574] });
map.on('load', function () {
map.addLayer({
'id': 'population',
'type': 'circle',
'source': {
type: 'vector',
url: 'mapbox://examples.8fgz4egr'
},
'source-layer': 'sf2010',
'paint': {
// make circles larger as the user zooms from z12 to z22
'circle-radius': {
'base': 1.75,
'stops': [[12, 2], [22, 180]]
},
// color circles by ethnicity, using data-driven styles
'circle-color': {
property: 'ethnicity',
type: 'categorical',
stops: [
['White', '#fbb03b'],
['Black', '#223b53'],
['Hispanic', '#e55e5e'],
['Asian', '#3bb2d0'],
['Other', '#ccc']]
}
}
}); }); </script>
My question is that I have a size-variable dataset, which is the result of user queries, and I would like to visualize my dataset.
How to use mapbox to obtain this behavior?
Thank you.

If the data is small enough, you simple load it all into the browser as a GeoJSON object, then display it with a geojson source. See this example.
If the data changes, you simple update the source object with .setData(newdata): example.

Related

How to retrieve data from JSON file without manually entering the data mapbox

I want to use a JSON file containing coordinates to plot points on a map with Mapbox and add markers at those locations. I've followed a few of their tutorials and searched elsewhere (stack overflow, Github etc) to see if I could find a solution but nothing seemed to work. I'm not getting any errors when I open the HTML file in the browser but the markers aren't appearing on the map at the JSON's coordinates and I'm not really sure how to get the JSON's coordinates to be read and then plotted on the map. I want the JSON to be used from the same folder as the project and not a URL so this didn't work for me either.
<script>
mapboxgl.accessToken = 'pk.eyJ1Ijoiam1hcHNkamFuZ28iLCJhIjoiY2tydzIwazc4MGNnODJvb2VhNHNhZDd5diJ9.iwGIdgMHrcjbNu1xJRAElQ';
const map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/streets-v11',
// style: 'mapbox://styles/mapbox/light-v10',
center: [-0.19346, 51.50405],
zoom: 9
});
map.on('load', () => {
map.addLayer({
id: 'restaurants',
type: 'Point',
source: {
type: 'geojson',
data: './restaurants.json' // replace this with the url of your own geojson
},
paint: {
'circle-radius': [
'interpolate',
['linear'],
['number', ['get', 'coordinates']],
0,
4,
5,
24
],
'circle-color': [
'interpolate',
['linear'],
['number', ['get', 'coordinates']],
0,
1,
2,
3,
4,
5,
],
'circle-opacity': 0.8
}
});
});
I don't know if this is your only error, but this line:
type: 'Point',
should be:
type: 'circle',

Changing property of a geojson feature dynamically on mapbox

I've been working with mapboxgl for a while, and I need to change the color of an circle based on the user's location. The circle starts with a color, if the user is on top of the circle, it changes to another color, and based on the interaction that the user has with the application, it changes the color again.
This is my source and layer data:
const pontosCircle = pontos.map((pointRoute) => ({
id: pointRoute.order,
type: 'Feature',
properties: { collected: 0, name: pointRoute.order },
geometry: { type: 'Point', coordinates: pointRoute.coordinates }
}));
const sourceId = 'pontos';
const source = {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: pontosCircle
}
};
const layerCircles = {
id: 'pontosRota',
type: 'circle',
source: sourceId,
paint: {
'circle-color': [
'case',
['==', ['get', 'collected'], 0],
'rgba(235, 68, 90, .8)',
['==', ['get', 'collected'], 1],
'rgba(17, 105, 54, .8)',
['==', ['get', 'collected'], 2],
'#ffffff',
'#000000'
],
'circle-stroke-width': 2,
'circle-stroke-color': [
'case',
['==', ['get', 'collected'], 0],
'rgba(235, 68, 90, .8)',
['==', ['get', 'collected'], 1],
'rgba(17, 105, 54, .8)',
['==', ['get', 'collected'], 2],
'#ffffff',
'#000000'
],
'circle-radius': {
stops: [
[0, 0],
[20, metersToPixelsAtMaxZoom(rota.raioColeta, rota.pontos[0].ponto.coordinates[1])]
],
base: 2
}
}
};
const layerLabels = {
id: 'pontosRota-labels',
type: 'symbol',
source: sourceId,
layout: {
'text-field': '{name}',
'text-size': 14
}
};
And this is the code that loads the layer/source into mapbox:
if (!map.getSource(sourceId)) {
map.addSource(sourceId, source);
}
if (!map.getLayer(layerCircles.id) && !map.getLayer(layerLabels.id)) {
map.addLayer(layerCircles);
map.addLayer(layerLabels);
}
I tried a lot of examples that could help me change the property collected from the data, but couldn't get it to work. Should i remove all of the layers and sources everytime that I need to change the data, or is there another way to paint only one of the circles?
I think that the setData() method that is available for GeoJSON sources in Mapbox GL JS is what you are looking for. The method allows you to update the underlying source data and triggers a map re-render. The data-driven styling should then kick in and style your updates layers as desired.
https://docs.mapbox.com/mapbox-gl-js/api/sources/#geojsonsource#setdata
Here is a pseudo-code example
map.getSource("source-id").setData(updatedGeoJSONData);
I'm in the process of putting together a Mapbox Developers Handbook that will include guides on this kind of stuff. It isn't done yet but you can follow along for updates and get notified when it is released here.

What is the source and it's format for the data points plotted on this map from mapbox?

I found the below code in the MapBox website, I am unable to find out how exactly the data is received to plot the data-driven circles on the map. There is a url "mapbox://examples.8fgz4egr" present in the 'source' but what kind of data is it ? is it json or what ? How do I change the source and put my own ?
https://www.mapbox.com/mapbox-gl-js/example/data-driven-circle-colors/
<script> mapboxgl.accessToken = 'ACCESS_TOKEN; var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://styles/mapbox/light-v9',
zoom: 12,
center: [-122.447303, 37.753574] });
map.on('load', function () {
map.addLayer({
'id': 'population',
'type': 'circle',
'source': {
type: 'vector',
url: 'mapbox://examples.8fgz4egr'
},
'source-layer': 'sf2010',
'paint': {
// make circles larger as the user zooms from z12 to z22
'circle-radius': {
'base': 1.75,
'stops': [[12, 2], [22, 180]]
},
// color circles by ethnicity, using data-driven styles
'circle-color': {
property: 'ethnicity',
type: 'categorical',
stops: [
['White', '#fbb03b'],
['Black', '#223b53'],
['Hispanic', '#e55e5e'],
['Asian', '#3bb2d0'],
['Other', '#ccc']]
}
}
}); }); </script>
It's vector tiles as you can see from the type value of the source property. Here is an in depth explanation on what vector tiles are and how they work: https://www.mapbox.com/vector-tiles/
Very roughly it's GeoJSON sliced into map tiles.
For simplicity's sake you can switch out the source for a geojson source and connect the circle layer to it:
map.addLayer({
type: 'circle',
id: 'my-layer',
source: {
type: 'geosjon'
data: /* url to GeoJSON or inlined FeaturedCollection */
}
})

How to achieve better clustering for indoor map on mapbox?

I am using some default mapbox clustering, which is not enough for indoor map of building. Here is my example
map.addSource('maintenance_events_on_map', {
type: 'geojson',
cluster: true,
clusterMaxZoom: 22, // Max zoom to cluster points on
clusterRadius: 1, // Radius
data: JSON.parse(maintenance_events_on_map)
}).addLayer({
id: 'clusters',
type: 'circle',
source: 'maintenance_events_on_map',
paint: {
'circle-radius': 20,
'circle-color': '#973901'
}
}).addLayer({
id: 'cluster-label',
type:'symbol',
source:'maintenance_events_on_map',
layout:{
'text-field': "{point_count}"
}
});
The output is following:
I need it to be on the level of indoor building:
The only way achieving this is using Mapbox Studio, where you can upload custom icons, which easily can be called in the layer properties, while creating a layer. These icons are clusterable and this works much more better.

Mapbox-gl.js logs lots of 404 errors for tiles in the browser console

Ok, I am using Mapbox as my mapping library, I render the map layers using the tiles (geojson) uploaded to the mapbox account. Demo here
The map renders properly but I get lots of 404 not found errors for the source tiles.
How to get rid of these errors?
Here is my code:
mapboxgl.accessToken = 'token';
var map = new mapboxgl.Map({
container: 'map',
//style: 'mapbox://styles/mapbox/streets-v9',
style: 'mapbox://styles/saurabhp/cizmll8v200452sqj5c16hc55?optimize=true', // optimize=true,
center: [-1.41, 6.32],
zoom: 5
});
map.on('load', function () {
map.addLayer({
'id': 'maine',
'type': 'fill',
'layout': {},
'paint': {
'fill-color': {
property: 'NDVI6',
stops: [
[0, '#F2F12D'],
[1, '#EED322'],
[2, '#E6B71E'],
[3, '#DA9C20'],
[4, '#CA8323'],
[5, '#B86B25'],
[6, '#A25626'],
[7, '#8B4225'],
[8, '#723122']
]
},
'fill-opacity': 0.8
},
'source': {
'type': 'vector',
'url': 'mapbox://saurabhp.cizs70g1e003033lkqw0u2rjj-6kayy'
},
"source-layer": "ghanaTestTileset",
});
});
The easiest way is to replace the default error handler, filtering out the "Not Found" message:
map.on('error', e => {
// Hide those annoying non-error errors
if (e && e.error !== 'Error: Not Found')
console.error(e);
});
As pointed out by mollymerp, updating the mapbox-gl js from 0.32.0 to 0.37.0 resolved the issue for me.

Categories

Resources