Mapbox GL setData to update layer with multiple markers - mapbox

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.

Related

Heatmap from geojson points in leaflet

I am attempting to create a simple heatmap from a feature collection of points using leaflet's heatmap plugin. After successfully getting the json data from an ajax call, I create an empty coords array and push coordinates from each feature.
However, this method does not work and neither does the geojson2heat function. There are no errors in the console. What am I doing wrong and does anyone know of a workaround?
var map = L.map('map').setView([50.0647, 19.9450], 12);
var tiles = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors',
}).addTo(map);
var geojsonLayer = new L.GeoJSON.AJAX("newmap.geojson");
coords = [];
function onEachFeature(feature, layer) {
coords.push(feature.geometry.coordinates);
};
L.GeoJSON(geojsonLayer, {
onEachFeature: onEachFeature
})
var heat = L.heatLayer(coords).addTo(map);
The structure of the geojson is standard:
{
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },
"features": [
{ "type": "Feature", "properties": { "st_x": 19.952030181884801, "st_y": 50.055513141929701 }, "geometry": { "type": "Point", "coordinates": [ 19.952030181884801, 50.055513141929701 ] } },
{ "type": "Feature", "properties": { "st_x": 18.672015, "st_y": 50.287181666666697 }, "geometry": { "type": "Point", "coordinates": [ 18.672015, 50.287181666666697 ] } },
I am mostly doing the same as you but with Mapbox, which is based on Leaflet.
The problem I had is that the latitude and longitude coordinates of the GeoJSON were reversed. There were no errors on console either- points were just not showing on map. So, you need:
"coordinates": [ longitude, latitude ]
Hope that's the issue.

Leaflet FeatureCollection: LatLong is undefined

I am looking to create a GeoJson instance from a database request with PHP.
I am using this package to create the instance:
http://jmikola.github.io/geojson/api/class-GeoJson.Feature.FeatureCollection.html
I have created the FeatureCollection but I am getting an error
"Error: Invalid LatLng object: (undefined, undefined)"
even though my coordinates are floats.
However, the coordinates are not coming through an array [,], but as a Javascript objects {,} that are inside an array and maybe this is the problem?
Secondly, I think I am having trouble setting the CRS. I can successfully create the GeoJSON in QGIS and it appears at the top of the FeatureCollection but with this package in PHP it appears towards the end.
My feature collection looks like this:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "MultiPoint",
"coordinates": [
{...},
{...}
]
},
"properties": [
{...},
{...}
],
"id": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
}
}
]
}
I hope someone can help because I have been trawling through forums for hours!
Cheers
Yes, the coordinates and properties must be arrays, and not objects. Therefore, you can transform those before trying to create your geoJSON, like this:
//loop through all your features
featureCollection.features.forEach(function(feature) {
// first the coordinates in the geometry property
feature.geometry.coordinates.forEach(function(coord, index) {
feature.geometry.coordinates[index] = [coord.lat, coord.lng];
});
// then those in the properties
feature.properties.forEach(function(prop, index) {
feature.properties[index] = [prop.lat, prop.lng];
});
});

Leaflet js geojson coordinates = Lat/lng from googlemap

I am new to leaflet js
Reading the geojson section of leaflet js web site.
A quick question, coordinates in the geojson format, is it same as the lay/lng, which we can get from google map ?
Jimmy
yes but you have to invert lat and lng.
For example if you click on Paris you will get following coordinates with GoogleMap: 48.857031, 2.346526
If you generate some geojson with http://geojson.io/ you will get:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": {},
"geometry": {
"type": "Point",
"coordinates": [
2.349529266357422,
48.856414043180365
]
}
}
]
}
Also note that GoogleMap only handles 6 decimals (which is ample)

Access geojson property of a layer in a featuregroup in Mapbox

I have a GEOJSON which I added to the featuregroup in my Mapbox map like this:
var featureCollection = {
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"id": 1
},
"geometry": {
"type": "Point",
"coordinates": [0, 0]
}
},{
"type": "Feature",
"properties": {
"id": 2
},
"geometry": {
"type": "Point",
"coordinates": [30, 30]
}
},{
"type": "Feature",
"properties": {
"id": 3
},
"geometry": {
"type": "Point",
"coordinates": [-30, -30]
}
}]
};
var geojson = L.geoJson(featureCollection);
var featureGroup = L.featureGroup().addTo(map);
featureGroup.addLayer(geojson);
Now, I wish to access the id property of each layer while looping through the featuregroup, so that I can pass it as an argument to another function. In the case of a featurelayer, I can easily access it using something like this:
var featureLayer = L.mapbox.featureLayer(featureCollection).addTo(map);
featureLayer.eachLayer(function (layer) {
layer.on('click', function (e) {
console.log('Clicked feature ID: ' + e.target.feature.properties.id);
});
});
But I want to be able to access it while looping inside a featuregroup, and also I want to be able to do it without a 'click' or any such event. For example, ideally I would use something like this:
featureGroup.eachLayer(function (layer) {
var id = layer.feature.properties.id;
testfunction(id);
});
I haven't been able to figure out how to do that. I've tried searching online, but because I'm new to this, I probably haven't been using the right keywords in my search.
geojson is nested within featureGroup, so when your eachLayer function runs, it is not operating on the individual features within geojson, but instead on geojson itself. To extract each feature's id property, you will need to go one level deeper and iterate over the features within geojson.
Fortunately, the L.GeoJson class also supports the eachLayer method (because it is an extension of L.FeatureGroup, which is itself an extension of L.LayerGroup). To print the id of each feature, you could just use the eachLayer method directly on geojson:
geojson.eachLayer(function (layer) {
var id = layer.feature.properties.id;
testfunction(id);
});
Or, if you have a bunch of L.GeoJson objects nested within featureGroup, you can use:
featureGroup.eachLayer(function (layer) {
layer.eachLayer(function (layer) {
var id = layer.feature.properties.id;
testfunction(id);
});
});

How to add a GeoJSON layer in GraphHopper?

I have a GeoJSON file containing POIs that I'd like to be able to display within a separate GraphHopper layer. After several tries and search over internet, I just can't manage to get a way to do it.
This is a sample of the GeoJSON file (I checked the whole file with JSON validator and it was OK).
{"type": "Feature",
"properties": {
"fee": "no",
"bicycle_parking": "anchors",
"ref": "PVNAN23",
"address": "Rue Gabriel Goudy 44200 Nantes",
"name": "Pirmil P+R",
"capacity": "24",
"park_ride": "yes",
"amenity": "bicycle_parking",
"covered": "yes"
},
"geometry": {"type": "Point", "coordinates": [-1.5406709, 47.1960031]}},
{"type": "Feature",
"properties": {
"bicycle_parking": "stands",
"addr:postcode": "44000",
"addr:country": "FR",
"name": "Madeleine",
"capacity": "6",
"amenity": "bicycle_parking",
"addr:street": "chaussée de la Madeleine",
"note": "vérifié",
"addr:city": "Nantes",
"covered": "no",
"addr:housenumber": "35"
},
"geometry": {"type": "Point", "coordinates": [-1.55076671448, 47.21000114109]}}
]}
I tried what is explained in How to load external geojson file into leaflet map but I cannot get it working.
If your JSON is valid that doesn't mean you're working with a valid GeoJSON object. For instance: {"foo": "bar"} is perfectly valid JSON but in no way a valid GeoJSON object. L.GeoJSON, leaflet's GeoJSON layer expects a FeatureCollection or an array containing Features.
A valid FeatureCollection:
{
"type": "FeatureCollection",
"features": [{
"type": "Feature",
"properties": {
"id": 1
},
"geometry": {
"type": "Point",
"coordinates": [0,0]
}
},{
"type": "Feature",
"properties": {
"id": 2
},
"geometry": {
"type": "Point",
"coordinates": [1,1]
}
}]
}
Or just the array with features:
[{
"type": "Feature",
"properties": {
"id": 1
},
"geometry": {
"type": "Point",
"coordinates": [0,0]
}
},{
"type": "Feature",
"properties": {
"id": 2
},
"geometry": {
"type": "Point",
"coordinates": [1,1]
}
}]
(Note that just an array of features isn't a valid GeoJSON object but Leaflet will handle it without problems)
To load these into a L.GeoJson layer you'll need to make them available in your script. You could simple declare the object before you create the layer. For example:
// Declare GeoJSON object
var geojson = {
type: "FeatureCollection",
features: [
// Features here
]
}
// Create a new GeoJSON layer with geojson object
// And add to map (assuming your map instance is assigned to "map")
var layer = new L.GeoJSON(geojson).addTo(map);
But that will become quite a mess when you've got lots of features and it's always better to keep your logic and data separated so you should put your data object in a separate file. So let's say you've got the object stored in a file called "geo.json", then you can load the file with XHR/AJAX solution of your choice. I'm using jQuery in the following example:
// Fetch geo.json file and assign the data to geojson variable
$.getJSON('geo.json', function (geojson) {
// Create a new GeoJSON layer with GeoJSON object
// And add to map (assuming your map instance is assigned to "map")
var layer = new L.GeoJSON(geojson).addTo(map);
});
Here a working example on Plunker: http://plnkr.co/edit/Mh8p4F?p=preview