Choropleth Layer mapbox geojson not working - mapbox

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

Related

Mapbox gl js - How to add multiple photo sources on a single layer

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/

How to change styles/properties of features by data from extra json file? (MapBox GL)

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/

Mapbox Multiple polygons from single geoson source

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.

What is the proper way to select and style markers on Mapbox GL JS?

I am working with a Mapbox map that has points. I would like to know the correct procedure for adding a marker-symbol. Here is my GeoJSON:
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [
-89.12312324,
13.686886
]
},
"properties": {
"title": "Random Location",
"description": "Individual"
}
}
]
Here is an example from the Mapbox docs:
map.addLayer({
"id": "airport",
"source": "airports",
"source-layer": "ne_10m_airports",
"type": "symbol",
"layout": {
"icon-image": "airport-15",
"icon-padding": 0
},
"filter": ["in", "abbrev", ""]
});
When I use this
"layout": {
"icon-image": "marker-11",
"icon-allow-overlap": true,
}
I get little brown dots instead of the classic marker.
I am using
<script src='https://api.mapbox.com/mapbox-gl-js/v0.18.0/mapbox-gl.js'></script>
<link href='https://api.mapbox.com/mapbox-gl-js/v0.18.0/mapbox-gl.css' rel='stylesheet' />
and I am using the
style: 'mapbox://styles/mapbox/outdoors-v9', //stylesheet location
My entire script looks like this:
mapboxgl.accessToken = 'pk.mylongAkey';
var map = new mapboxgl.Map({
container: 'map', // container id
style: 'mapbox://styles/mapbox/outdoors-v9', //stylesheet location
center: [-88.866245, 13.770391], // starting position
zoom: 6 // starting zoom
});
var url = '/maps/index.json';
var source = new mapboxgl.GeoJSONSource({
data: url
});
map.on('load', function () {
map.addSource('location', source);
map.addLayer({
"id": "map",
"type": "symbol",
"source": "location",
"source-layer": 'location',
"layout": {
"icon-image": "marker-11",
"icon-allow-overlap": true,
}
});
});
map.on('click', function (e) {
var features = map.queryRenderedFeatures(e.point, { layers: ['map'] });
if (!features.length) {
return;
}
var feature = features[0];
// Populate the popup and set its coordinates
// based on the feature found.
var popup = new mapboxgl.Popup()
.setLngLat(feature.geometry.coordinates)
.setHTML(feature.properties.title)
.addTo(map);
});
// Use the same approach as above to indicate that the symbols are clickable
// by changing the cursor style to 'pointer'.
map.on('mousemove', function (e) {
var features = map.queryRenderedFeatures(e.point, { layers: ['map'] });
map.getCanvas().style.cursor = (features.length) ? 'pointer' : '';
});
Am I missing something? Also, the popups don't popup above the points, they popup over top of the icon. You can't tell with this little brown dot, but with the rocket for example the popup is in the middle of the rocket. Thanks!
Here is a screenshot
I am working with a Mapbox map that has points. I would like to know the correct procedure for adding a marker-symbol. Is it better to do it in the GeoJSON like:
...
Or is better to use layout like this:
...
Embedding style information in the GeoJSON (the former) is a specification called simplestyle, which is not supported in GL JS. Using layout (the latter) is the only way to style features in GL JS.
I get little brown dots instead of the classic marker.
Could you please provide a screenshot of this?
In the Mapbox Studio Editor, you need to make sure that you actually have an icon called "marker-11" in your icon library. If not, it doesn't know what you are referencing and will default to a dot.
Otherwise, everything else looks fine.

Mapbox GL setData to update layer with multiple markers

I have a Mapbox GL map with a single layer and multiple markers on that layer, I am trying to update a specific marker, so I am using setData in order to update only one marker but setData will reset the whole layer markers to add only that I am trying to update as the single marker on the whole layer, thus removing all old markers.
By trying to add multiple markers in GEOJson format as an array of GEOJson objects as shown below I get an error:
Uncaught Error: Input data is not a valid GeoJSON object.
code:
map.getSource('cafespots').setData([{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [31.331849098205566, 30.095422632059062]
},
"properties": {
"marker-symbol": "cafe"
}
},{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [31.39, 30.10]
},
"properties": {
"marker-symbol": "cafe"
}
}]);
Will appreciate it so much if someone can please help by telling me what I am doing wrong / missing here, thanks
setData expects a complete GeoJSON object (not just it's features) or a url pointing to a GeoJSON object.
You'll need to manage the state of the GeoJSON in your code and update the entire object via setData when a change is made.
var geojson = {
"type": "FeatureCollection",
"features": []
};
map.on('load', function() {
map.addSource('custom', {
"type": "geojson",
"data": geojson
});
// Add a marker feature to your geojson object
var marker {
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [0, 0]
}
};
geojson.features.push(marker);
map.getSource('custom').setData(geojson);
});
https://www.mapbox.com/mapbox-gl-js/example/measure/ is a good example that demonstrates this behaviour.