Changing property of a geojson feature dynamically on mapbox - javascript

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.

Related

queryRenderedFeatures doesnt work when i tried to get point data from map (mapbox)

I need to do something like that:
example
source
That is, when the user clicks at the accident point, they should see data about the accident, as a card of the accident that occurred (type ant other info from geojson file)
But my features from my layout doesnt returning from queryRenderedFeatures()
Anyway, if I tried to get data via queryRenderedFeatures() without options, like
const features = this.map.queryRenderedFeatures(event.point);
I dont get data from MY layer I get other data but not mine
help :(
this.map.on('click', (event) => {
const features = this.map.queryRenderedFeatures(event.point, {layers: ['clusters', 'point']})
console.log(features)
})
layers:
this.map.addLayer({
id: 'clusters',
type: 'circle',
source: 'accidents',
filter: ['has', 'point_count'],
paint: {
'circle-color': [
'step',
['get', 'point_count'],
'#51bbd6',
100,
'#f1f075',
750,
'#f28cb1'
],
'circle-radius': [
'step',
['get', 'point_count'],
20,
100,
30,
750,
40
]
}
});
this.map.addLayer({
id: 'point',
type: 'circle',
source: 'accidents',
filter: ['!', ['has', 'point_count']],
paint: {
'circle-color': '#11b4da',
'circle-radius': 10,
'circle-stroke-width': 1,
'circle-stroke-color': '#fff'
}
});

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',

Mapbox, bounce corresponding marker when hovering over sidebar element

I want to highlight a marker on a map, when I hover the correspondent item on a sidebar.
I have the same items showing in the map, and also on a side bar.
So i want that whem you hover over a item on a sidebar, the corresponding marker bounces, or moves or does something.
I have a map.on('load', function() {...}
Where i load a source markers, activate culsters, and add some layers,
The source is a geojson file I build with data from my backend.
Where i load a source, activate culsters, and add some layers:
map.on('load', function() {
map.addSource('users', {
type: "geojson",
data: markers,
cluster: true,
});
map.addLayer({
id: "singles",
type: "circle",
source: "users",
filter: ["!has", "point_count"],
paint: {
'circle-radius': {
'base': 10,
'stops': [[5, 20], [15, 500]]
},
'circle-color': '#ddffc8',
}
});
map.addLayer({
id: "clusters",
type: "circle",
source: "users",
filter: ["has", "point_count"],
paint: {
"circle-color": '#ddffc8',
'circle-radius': {
'base': 10,
'stops': [[5, 20], [15, 500]]
},
}
});
map.addLayer({
id: "cluster-count",
type: "symbol",
source: "users",
filter: ["has", "point_count"],
layout: {
"text-field": "{point_count_abbreviated}",
"text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],
"text-size": 12
}
})
})
I can acces the GeoJson, but its only a json file with the info of each of the markers, there is no property in it like for example marker.bounce or so...
So, how can I make it so that when i hover over a sidebar item, the corrresponding markers bouces, or changes icon or does something?
Thanks.

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 */
}
})

Using different symbols for plotting data not working

I am attempting to use a different symbol for one of my data series on my flot graph as it is at a much larger scale then the rest of the data. I am using this example as reference: http://www.flotcharts.org/flot/examples/symbols/index.html
Here is what I have so far:
My includes:
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="jquery.flot.js"></script>
<script type="text/javascript" src="jquery.flot.symbol.js"></script>
I then configure my flot options like so:
var options = {
grid: {hoverable : true},
xaxis: { mode: "time", timeformat: "%H:%M", tickLength: 1},
series: { points : { show: true } }
};
I then actually plot the data:
$.plot('#placeholder', [{
data: my_data,
lines: { show : true},
points: { symbol: "square"},
color: '#CB4B4B',
label: 'My Data'
}], options);
}
However, flot is still graphing the points as the default circle. I get no error messages in firebug and I have even tried adding a logging message in the jquery.flot.symbol.js library itself to see if the "square" handler is even being called like so:
var handlers = {
square: function (ctx, x, y, radius, shadow) {
console.log("Square handler was called");
// pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2
var size = radius * Math.sqrt(Math.PI) / 2;
ctx.rect(x - size, y - size, size + size, size + size);
},
I am getting no console messages so I am assuming the handler is not getting called correctly. Am I missing something here?
EDIT:
Example of data I am trying to plot:
var d1 = [
[1364342400000, 208],
[1364346000000, 107],
[1364353200000, 42],
[1364371200000, 1680],
[1364360400000, 52],
[1364349600000, 67],
[1364385600000, 1118],
[1364367600000, 163],
[1364382000000, 1359],
[1364378400000, 1468],
[1364389200000, 1023],
[1364356800000, 63],
[1364374800000, 1601],
[1364392800000, 556],
[1364364000000, 84],
],
d2 = [
[1364342400000, 86],
[1364346000000, 42],
[1364353200000, 13],
[1364371200000, 458],
[1364360400000, 10],
[1364349600000, 22],
[1364385600000, 453],
[1364367600000, 45],
[1364382000000, 369],
[1364378400000, 379],
[1364389200000, 358],
[1364356800000, 17],
[1364374800000, 471],
[1364392800000, 147],
[1364364000000, 16],
],
d3 = [
[1364342400000, 7],
[1364346000000, 5],
[1364382000000, 11709],
[1364371200000, 58336],
[1364360400000, 1],
[1364349600000, 1],
[1364367600000, 2],
[1364389200000, 1191],
[1364378400000, 9085],
[1364385600000, 4688],
[1364374800000, 9386],
[1364392800000, 1140],
[1364364000000, 1],
];
I have also edited my options parameter and how the plot function is called:
var options = {
grid: {hoverable : true},
xaxis: { mode: "time", timeformat: "%H:%M", tickLength: 1}
};
$.plot("#placeholder", [{
data: d1,
lines: { show : true },
points: { show: true},
color: '#EDC240',
label: "d1"
}, {
data: d2,
lines: { show : true },
points: { show : true},
color: '#AFD8F8',
label: "d2"
}, {
data: d3,
yaxis: 2,
lines: { show : true},
points: { show: true, symbol: "square"},
color: '#CB4B4B',
label: "d3"
}], options);
I am also sure that the symbol library is being included because I have added some logging itself to the library and that is showing up fine.
I see no issue with what you've done. I made a quick working example here: http://jsfiddle.net/ryleyb/shLtU/1/
I would guess that you haven't included the symbol library (even though you say you have).
Or show your data, might somehow be an issue there (doubtful?).
This is the full flot code I ran to make a working example (plus including flot and the symbol library):
$.plot('#placeholder', [{
data: [
[1, 1],
[2, 3],
[4, 4],
[5, 9]
],
lines: {
show: true
},
points: {
show: true,
symbol: "square"
},
color: '#CB4B4B',
label: 'My Data'
}]);

Categories

Resources