Using Mapbox JS I'm trying to draw multiple polygons from a single Geoson source. I'm following
the tutorial for multiple geometries from one Geoson source (Mapbox link) combined with the realtime data documentation (Mapbox link). However, I get no polygon drawn on the map. Is the FeatureCollection the right approach for drawing and updating multiple polygons? The number of polygons can vary in time, as well.
Withing the map.on('load'...), I got this source, layer and data loading:
map.addSource('fire', { type: 'geojson', data: fire_url });
/*
map.addLayer({
'id': 'fire',
'type': 'fill',
'source': 'fire',
'paint': {
'fill-color': '#888888',
'fill-opacity': 0.4
},
'filter': ['==', '$type', 'Polygon']
});
window.setInterval(function() {
console.log('got data');
map.getSource('fire').setData(fire_url);
}, 1000);
Example of data I'm updating live:
{
"features": [
{
"geometry": {
"coordinates": [
[
-8.318497,
39.954263
],
[
-8.317997,
39.954263
],
[
-8.317997,
39.959263
],
[
-8.318497,
39.954263
]
],
"type": "Polygon"
},
"properties": {},
"type": "Feature"
}
],
"type": "FeatureCollection"
}
Your GeoJSON is invalid. You can test it at http://geojsonlint.com/
Polygons are not just arrays of points (like LineStrings). They are arrays of arrays of points, because there can be holes and islands within the outer polygon.
Related
Every 2 seconds I create a new image source and a new layer for that source:
map.addSource("source_" + photo_id, {
"type": "image",
"url": photo_url,
"coordinates": [... ]
})
map.addLayer({
"id": "layer_" + photo_id,
"source": "source_" + photo_id,
"type": "raster",
"paint": {"raster-opacity": 0.6}
})
That means for every photo, a new layer is created.
I was wondering, is it possible to add multiple photo sources on the same layer in order to avoid this multiple layer creation?
map.getSource('photoSource').updateImage(...) won't work because I would like all the previous photos to also remain on the map
Basically my goal is to separate the photos on the map into groups, in order to be able later to remove a certain group of photos, and that would be possible with multiple sources in one layer.
This is 100% possible with the expression syntax.
{
'type': 'Feature',
'geometry': {
'type': 'Point',
'coordinates': [this.long, this.lat]
},
'properties': {
'icon': 'bus-generic'
}}
If you have a property, you can query it and use it in the layer definition to display different icons:
map.addLayer({
'id': 'bus-layer',
'type': 'symbol',
'source': 'bus-source', // reference the data source
'layout': {
'icon-image': ['get', 'icon'], // reference the icon in properties
'icon-size': 0.2,
}
});
See this example over here!
https://docs.mapbox.com/mapbox-gl-js/example/add-image-missing-generated/
I want to draw thousands of polygons with random color, how can I do it without creating tons of layers?
Now I use only one layer with MultiPolygon, it works fine, but I want same thing but filled with random colors.
How can I do that?
Thanks.
This is possible, see this example: https://docs.mapbox.com/mapbox-gl-js/example/data-driven-circle-colors/
You can do the same, but you would have to add properties to the features that describe your polygons, that can be used to determine the color.
In this example the source holds circles. Their color is changed according to their ethnicity property in the source:
Sample source feature:
{
"type": "Feature",
"properties": {
"ethnicity": "White"
},
"geometry": {
"type": "Point",
"coordinates": [ -122.447303, 37.753574 ]
}
}
Adding all source features in 1 layer and adjusting color with match reference:
map.addLayer({
'id': 'population',
'type': 'circle',
'source': 'ethnicity',
'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 a match expression
// https://docs.mapbox.com/mapbox-gl-js/style-spec/#expressions-match
'circle-color': [
'match',
['get', 'ethnicity'],
'White',
'#fbb03b',
'Black',
'#223b53',
'Hispanic',
'#e55e5e',
'Asian',
'#3bb2d0',
/* other */ '#ccc'
]
}
});
So far I have a map (MapBox GL) that draws counties with borders.
map.addSource('states', {
'type': 'geojson',
'data': '/geojson/county_boundaries.geojson'
});
map.addLayer({ // adding borders:
'id': 'state-borders',
'type': 'line',
'source': 'states',
'layout': {},
'paint': {
'line-color': '#627BC1',
'line-width': 2
}
});
This county_borders.geojson has items (features) with parameter 'name'.
...
"features": [
{ "type": "Feature", "id": 8, "properties": { "name": "New York", ...
I have another stats.json file with properties for most of the features, where 'name' is the main key.
"New York": {
"Population": "500123",
"Food Consumption Level": "3",
"Color": "#e67800"
},
I am new to MapBox, and with so many parameters-based functions I am getting lost. Please help me to change the fill color of all states with the Color from stats.json file by looking up their names ("New York" etc). I suppose I need to iterate through all the features and set their filling somehow.
The only way I have found to fill the states with the same default color is like this:
map.addLayer({
'id': 'state-fills',
'type': 'fill',
'source': 'states',
'layout': {},
'paint': {
'fill-color': '#627BC1',
'fill-opacity': [
'case',
['boolean', ['feature-state', 'hover'], false],
1,
0.5
]
}
});
It is working to fill all the states. But not what I need. I would like to dynamically modify color of each state runtime, without changing original geojson file. (Other params in data.json I show in popup, which works fine with this extra file approach.)
Instead of adding your original GeoJSON file as a source to your map, you can add the stats to the GeoJSON with Javascript before adding the source:
var geojson = addStats(originalGeojson, stats);
map.addSource('states', {
'type': 'geojson',
'data': geojson
});
function addStats(geojson, stats) {
geojson.features.forEach((feature) => {
var statsForFeature = stats[feature.properties.name];
if (statsForFeature) {
// add stats to the feature's properties
feature.properties = Object.assign(feature.properties, statsForFeature);
}
});
return geojson;
}
After that, you can use data-driven styling with layer type 'fill' to color your features:
map.addLayer({ // adding borders:
'id': 'state-borders',
// use type 'fill'
'type': 'fill',
'source': 'states',
'layout': {},
'paint': {
'fill-outline-color': '#627BC1',
// use data-driven styling
'fill-color': ['get', 'Color'],
},
});
Here is a working example demonstrating this technique: https://jsfiddle.net/0s17mqvh/
I got this:
map.addLayer({
"id": "places",
"type": "symbol",
"source": {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": features
}
},
"layout": {
"icon-image": "{icon}-15",
"text-field": "{title}",
"text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
"text-offset": [0, 0.6],
"text-anchor": "top"
}
});
Where features is array of objects like this:
{
"id": SOME_ID,
"type": "Feature",
"properties": {
"title": SOME_TITLE,
"icon": "monument"
},
"geometry": {
"type": "Point",
"coordinates": SOME_COORDINATES
}
}
I want to delete this specific feature, NOT THE WHOLE places LAYER, how can it be done?
I have tried to create for each feature, a designated layer with predefined ID, but
when tried to remove it using map.removeLayer(SOME_ID) this told me that the
layer id does not exist.
How to delete specific geojson feature from feature collection in mapbox, without delete the wole
layer, just the json data?
If you want to hide the feature on the map, then you don't have to remove it from the source. You can filter this feature out using filter, so it wouldn't be rendered on the map.
Consider example:
map.addLayer({
id: 'points',
type: 'circle',
source: {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: [
{
type: 'Feature',
id: 1,
properties: {},
geometry: {
type: 'Point',
coordinates: [127.61718749999999, 66.51326044311185]
}
},
{
type: 'Feature',
id: 2,
properties: {},
geometry: {
type: 'Point',
coordinates: [79.1015625, 72.50172235139388]
}
},
{
type: 'Feature',
id: 3,
properties: {},
geometry: {
type: 'Point',
coordinates: [61.17187499999999, 31.952162238024975]
}
}
]
}
},
filter: ['!=', '$id', 3]
});
This will render all features except feature with id=3.
You can also set this kind of filters using map.setFilter method.
map.setFilter('my-layer', ['==', 'name', 'USA']);
Edit:
If you really want to remove a specific feature from the source, you can filter this feature from the features array and update the source using setData:
map.getSource('places').setData({
"type": "FeatureCollection",
features
});
I am newbie to mapbox. I have to populate graph like below example
https://docs.mapbox.com/mapbox-gl-js/example/updating-choropleth/
I am using geojson file as a source but it is not working.
map.on('load', function() {
map.addSource('tls_demand', {
'type': 'geojson',
'url': 'http://1xx.2xx.1xx.1xx/xxxx.geojson'
});
map.addLayer({
"id": "tls_projection",
"type": "fill",
"source": "tls_demand",
"filter": ["==", "$type", "MultiPolygon"],
'paint': {
"line-color": "red",
'fill-opacity': 0.75
}
});
});
Can anyone pls suggest how to do it?
I had some time to play with this.
Here's a snippet and also there's codepen at the bottom.
map.on("load", function() {
map.addSource("tls_demand", {
type: "geojson",
data: "https://gist.githubusercontent.com/androidfanatic/99de0a21907791fc2d57570df19455f6/raw/9710b3c69f0591bc6ca7730b0b6eebe2349b7571/DeoriaBoundary1.geojson"
});
map.addLayer({
id: "tls_projection",
type: "fill",
source: "tls_demand",
filter: ["==", "$type", "Polygon"],
paint: {
"fill-outline-color": "red",
"fill-color": "red",
"fill-opacity": 0.2
}
});
Couple of observations that I had:
MultiPolygon isn't a valid filter option.
The server that is hosting GeoJSON doesn't allow cross origin requests so you'd have to re-host.
The GeoJSON isn't in EPSG:4326 which is the only coordinate system supported by mapboxgl-js so you'd have to project the geojson to EPSG:4326. I used ogr2ogr2 for that and the command is.
ogr2ogr DeoriaBoundary1.geojson -t_srs "EPSG:4326" DeoriaBoundary.geojson
A layer of type fill must provide fill-color paint property.
To pass URL to source, you'd say "data": "https://domain.tld/url-to-geojson" instead of url property.
You can see all of this in action here: https://codepen.io/manishraj/full/jONzBEK