So I have two separate geoJSON files in my scripts folder, one for drawing boundary lines and one for putting markers. Each geoJSON file has different contents, for example:
var putMarkers = {
type: 'Feature',
"geometry": { "type": "Point", "coordinates": [-77.03, 38.90]},
"properties": {
"image": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ef/Cherry_Blossoms_and_Washington_Monument.jpg/320px-Cherry_Blossoms_and_Washington_Monument.jpg",
"url": "https://en.wikipedia.org/wiki/Washington,_D.C.",
"marker-symbol": "star",
"marker-color": "#ff8888",
"marker-size": "large",
"city": "Washington, D.C."
}
}
and another one:
var states = {"type":"FeatureCollection","features":[
{"type":"Feature","id":"01","properties":{"name":"Alabama"},"geometry":{"type":"Polygon","coordinates":[[[-87.359296,35.00118],[-85.606675,34.984749],[-85.431413,34.124869],[-85.184951,32.859696],[-85.069935,32.580372],[-84.960397,32.421541],[-85.004212,32.322956],[-84.889196,32.262709],[-85.058981,32.13674],[-85.053504,32.01077],[-85.141136,31.840985],[-85.042551,31.539753],[-85.113751,31.27686],[-85.004212,31.003013],[-85.497137,30.997536],[-87.600282,30.997536],[-87.633143,30.86609],[-87.408589,30.674397],[-87.446927,30.510088],[-87.37025,30.427934],[-87.518128,30.280057],[-87.655051,30.247195],[-87.90699,30.411504],[-87.934375,30.657966],[-88.011052,30.685351],[-88.10416,30.499135],[-88.137022,30.318396],[-88.394438,30.367688],[-88.471115,31.895754],[-88.241084,33.796253],[-88.098683,34.891641],[-88.202745,34.995703],[-87.359296,35.00118]]]}}}
putting one geoJSON in this format works,
var geoJson = L.mapbox.featureLayer(states).addTo(map);
but how do you add another geoJSON?
You can add as many featurelayers as you want:
var stateCollection = {"type": "FeatureCollection", "features": [...]};
var countyCollection = {"type": "FeatureCollection", "features": [...]};
var stateLayer = L.mapbox.featureLayer(stateCollection).addTo(map);
var countyLayer = L.mapbox.featureLayer(countyCollection).addTo(map);
Example on Plunker: http://plnkr.co/edit/lY08pEq3O9UYZrCFrbo8?p=preview
(add your own access token to test)
Related
I want to create a leaflet map to display site locations. The site data was loaded by leaflet ajax in the geojson format.
Then I use Leaflet.markercluster to create a cluster view and it works fine. But it seems the popup only shows the last site, no matter which icon I click on.
Here is my original code
function map_viewer(map, options){
var my_data = new L.GeoJSON.AJAX("http://127.0.0.1:8000/my_data/",{
onEachFeature: function(feature,layer){
layer.bindPopup(feature.properties.siteid);
clusters.on('click', function (e) {
this.bindPopup(feature.properties.siteid);
});
}
});
var clusters = L.markerClusterGroup();
my_data.on('data:loaded', function()
{
clusters.addLayer(my_data);
map.addLayer(clusters);
});
var groupedOverlays = {
"Layers": {
"cluster view": clusters
}
};
L.control.groupedLayers(groupedOverlays).addTo(map);
}
Updated on 2021-02-01:
I realise there are a few similar cases after go searching on google. However, when I refine my code based on the suggestion, the popup window never show up anymore:
function map_viewer(map, options){
var clusters = L.markerClusterGroup();
var my_data = new L.GeoJSON.AJAX("http://127.0.0.1:8000/my_data/",{
onEachFeature: function(feature,layer){
layer.bindPopup(feature.properties.siteid);
}
});
my_data.on('data:loaded', function()
{
clusters.addLayer(my_data);
map.addLayer(clusters);
});
}
Also, please refer to below a small part of the importing geojson dataset.
{"type": "FeatureCollection", "crs":
{"type": "name", "properties": {"name": "EPSG:4326"}}, "features": [
{"type": "Feature", "properties": {"siteid": 1, "latitude": -28.004959, "longitude": 153.428117, "pk": "1"}, "geometry": {"type": "MultiPoint", "coordinates": [[153.428117, -28.004959]]}},
{"type": "Feature", "properties": {"siteid": 2, "latitude": -33.870436, "longitude": 151.225013, "pk": "2"}, "geometry": {"type": "MultiPoint", "coordinates": [[151.225013, -33.870436]]}},
{"type": "Feature", "properties": {"siteid": 3, "latitude": -33.92677, "longitude": 151.21356, "pk": "3"}, "geometry": {"type": "MultiPoint", "coordinates": [[151.21356, -33.92677]]}},
{"type": "Feature", "properties": {"siteid": 4, "latitude": -33.854711, "longitude": 150.987657, "pk": "4"}, "geometry": {"type": "MultiPoint", "coordinates": [[150.987657, -33.854711]]}},
Conclusion:
I have fixed the issue just by converting the geometry type in my geojson dataset from "Multipoint" to "Point". It seems this plugin Leaflet.markercluster can only cluster view for Multipoints, but not able to display the bindPopup of each layer.
Fo me it is clear why the popup has the last id, because in the onEachFeature function you bind/overwrite every time the popup to the clusters with the new siteid and so the last one is applied.
But when you add a popup to the the complete markercluster all layers have the same popup.
So change your code to:
var my_data = new L.GeoJSON.AJAX("http://127.0.0.1:8000/my_data/",{
onEachFeature: function(feature,layer){
layer.bindPopup(feature.properties.siteid);
}
});
Alright, I delved into this case for 2 day, eventually, I find the bug and fix it.
The geometry type in my geojson dataset is "Multipoint". It seems this plugin Leaflet.markercluster can only cluster view for Multipoints, but not able to display the bindPopup of each layer.
To fix this, I just need convert "Multipoint" to "Point.
Anyway, thanks heaps #Falke Design for your kind hints and the great example.
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.
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);
});
});
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
I'm trying to implement simplestyle's options for marker size and color , but can't get them to render. In this simple test case, I'm trying to follow Mapbox's own example quite closely:
var myData = [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [4.509373,51.932994]
},
"properties": {
"marker-size": "large",
"marker-color": "#ffcc00"
}
}
];
var map = L.mapbox.map('map', 'examples.map-20v6611k')
.setView([51.932994,4.509373], 8);
L.geoJson(myData, { style: L.mapbox.simplestyle.style }).addTo(map);
fiddle
But the marker renders in default style. What am I missing?
OK, I've got it working using this extended function from this page of Mapbox's documentation:
L.geoJson(myData, {
pointToLayer: L.mapbox.marker.style,
style: function(feature) { return feature.properties; }
}).addTo(map);
The other Mapbox example didn't make it look like the pointToLayer argument was required, but whatever works:
fiddle
Another alternative would be to create a featureLayer based on your myData:
var featureLayer = L.mapbox.featureLayer(myData).addTo(map);
Your data will have to be an object, however, and not an array:
var myData = {
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [4.509373,51.932994]
},
"properties": {
"marker-size": "large",
"marker-color": "#ffcc00"
}
};