Fill Leaflet popup on click when acctually needed - javascript

I have a map with a lot of markers and a complex popup content, generated by a function called popupcontent(), which takes a lot of time to compute when it is done for all markers on the map with the oneachfeature function.
Is there a way to trigger a function in a popup only when it is actually opened instead of generating all the popups in the beginning? This would speed up loading time a lot.
This is my code so far (I am using the markerclusterer extension):
var geojson1 = L.geoJson(bigJson,{
onEachFeature: function (feature, layer) {
layer.bindPopup(popupcontent(feature,layer));
}
})
.addLayer(tiles);
var markers = L.markerClusterGroup({
spiderfyOnMaxZoom: true,
showCoverageOnHover: true,
zoomToBoundsOnClick: true,
disableClusteringAtZoom: 10,
removeOutsideVisibleBounds:true
});
var geoJsonLayer = L.geoJson(bigJson, {
});
markers.addLayer(geojson1);
map.addLayer(markers);
map.fitBounds(markers.getBounds());
Demo: http://stefang.cepheus.uberspace.de/farmshops/

I think what you're looking for is something like so (if your layer is an interactive layer):
onEachFeature: function (feature, layer) {
layer.once("click", ()=>{
layer.bindPopup(popupcontent(feature,layer)).openPopup();
});
}
Use "once" instead of "on" so it only gets binded once when the layer is clicked.

Related

Leaflet - openPopup() not showing with geoJSON

I am trying to bind popups to markers on a geoJSON layer. To do this, I am using the onEachFeature function:
var onEachFeature = function(feature, layer) {
layer.bindPopup("hello",
{closeButton:false,
autoClose: false,
closeOnClick: false,
className: "popup-custom"}).openPopup();
}
This does not result in a popup showing. The popup is created but I need to click on the marker to display it.
What am I missing to make the popup visible without clicking on the marker?
I am not using the pointToLayer function because I am also filtering the features with the filter fuction and using request to customise the popups and the markers (the popup binding is actually in a callback function).
You get a geojsonlayer as result and then you can open the popup for each layer:
var geojsonLayer = L.geoJSON(data, {
onEachFeature : onEachFeature
}).addTo(map);
geojsonLayer.eachLayer(function(layer){
layer.openPopup();
});
Thank you #Falke-Design, I got it to work. I had tried this but it did not work :
var geojsonLayer = L.geoJSON(data, {
onEachFeature : onEachFeature
});
geojsonLayer.eachLayer(function(layer){
layer.openPopup();
});
geojsonLayer.addTo(map);
Could you explain why this did not work?

Return name of geoJSON leaflet layer with click

I have a leaflet map with multiple geoJSON layers:
var site1 = new L.geoJSON(site1_geojson, {
onEachFeature: onEachFeature,
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, style);
}
}).addTo(map);
I would like the onEachFeature function to return the name (e.g. "site1") of the layer clicked on. Something like:
var nameOfLayer;
function onEachFeature(feature, layer) {
layer.on('click', function(e) {
nameOfLayer = ????
});
}
I've tried assigning feature and layer to nameOfLayer, but from what I can gather those look like just the point clicked on, not the geoJSON layer itself.
Is this possible to do with leaflet and JavaScript?
If you want a constant string:
var site1 = L.geoJSON(site1_geojson, {
pointToLayer: function (feature, latlng) {
return L.circleMarker(latlng, style);
}
}).addTo(map).bindPopup('Site 1');
If you want a popup specific to each layer / feature, and this specific content is reachable in each Feature properties, you can refer to Combining geojson and json for leaftlet and Leaflet omnivore + clustering markers + filtering marker cluster group

Remove custom geojson markers (loaded with Leaflet) after zoom

I'm adding some points to a map using the code below and they look great. I'm also adding some json polygons without issue.
When a certain zoom level is reached I would like the points and polygons to turn off. Using the map.removeLayer(name of polygon) turns off the polygon perfectly and then zoom back out I use map.addLayer(name of polygon) and they come back (using 'zoomend' and if else statement).
The point features do not react to the removeLayer function like the polygons do. I've also tried to harvestPoints.setOpacity(0) which does not work either. What code should I use to turn these geojson markers "on" and "off" like the polygon features?
function onEachPoint(feature, layer) {
layer.bindPopup(feature.properties.MGNT_AREA.toString());
layer.on('click', function (e) { layer.openPopup(); });
layer.bindLabel(feature.properties.MGNT_AREA.toString(), {
noHide: true,
className: "my-label",
offset: [-2, -25]
}).addTo(map);
};
var areaIcon = {
icon: L.icon({
iconUrl: 'labels/MonitoringIcon.png',
iconAnchor: [20, 24]
})
};
var harvestPoints = new L.GeoJSON.AJAX('labels/dfo_areas_point.json', {
onEachFeature: onEachPoint,
pointToLayer: function (feature, latlng) {
return L.marker(latlng, areaIcon);
}
});
Not sure exactly what is the root cause for your issue, as we are missing how exactly you reference yours points (markers) when you try to remove them from the map.
Normally, there should be no difference between polygons and points (markers) to achieve what you described (removing the layers from the map at certain zoom level, and add them back at other zooms).
Note that setOpacity is a method for L.Markers, whereas you apply it to harvestPoints which is your geoJson layer group.
What may happen is that you add individual points (markers) to your map (last instruction in your onEachPoint function), but try to remove the layer group harvestPoints from map. Because it seems to be never added to the map, nothing happens.
If you want to turn on/off ALL the points in your harvestPoints layer group at the same time, then you would simply add / remove that layer group to / from the map, instead of adding individual markers:
var harvestPoints = L.geoJson.ajax('labels/dfo_areas_point.json', {
onEachFeature: onEachPoint,
pointToLayer: function (feature, latlng) {
// make sure `areaIcon` is an OPTIONS objects
return L.marker(latlng, areaIcon);
}
}).addTo(map); // Adding the entire geoJson layer to the map.
map.on("zoomend", function () {
var newMapZoom = map.getZoom();
if (newMapZoom >= 13) {
map.addLayer(harvestPoints);
} else {
// Removing entire geoJson layer that contains the points.
map.removeLayer(harvestPoints);
}
});
Side note: popups open on click by default, you should not need to add an on click listener for that?
Demo: http://jsfiddle.net/ve2huzxw/62/

MapBox pop-up descriptions on markers not showing when clicking

I've integrated a MapBox map with marker clustering. For some reason the descriptions/titles will not show when you click on the marker.
Any idea why this is happening or how to fix it?
The page: https://vpnarea.com/front/member/signuptest
My MapBox code:
<script>
L.mapbox.accessToken = 'pk.xxxxxxxxxxxxxxxxxxxxxxx';
var markers = L.markerClusterGroup();
$.getJSON("https://vpnarea.com/data2.geojson-copy", function(data) {
var geojson = L.geoJson(data, {
onEachFeature: function (feature, layer) {
layer.setIcon(L.mapbox.marker.icon({'marker-color': 'f5c200','marker-size': 'small'}));
}
});
markers.addLayer(geojson);
// CONSTRUCT THE MAP
var map = L.mapbox.map('map1', 'vpnarea.m9b2pf4n') .setView([60, -55], 3);
markers.addTo(map);
});
</script>
You'll need to bind popups in order for them to appear: Mapbox.js's L.mapbox.featureLayer does this by default, but you're using L.geoJson, which does not. So you'll need to check out the Leaflet documentation for .bindPopup and use it.

When I use Leaflet's layer control, I get grey image because the visibility is hidden

I am using leaflet's layer control to change the disableClusteringAtZoom when it's toggled but I get
<div class="leaflet-tile-container leaflet-zoom-animated" style="visibility: hidden;">
for the tiled images. So I can see all the markers but I cannot see the maps when I zoom in or zoom out after changing the layer for the first time.
function initLayers() {
markers = new L.MarkerClusterGroup({
disableClusteringAtZoom: 11
});
markers2 = new L.MarkerClusterGroup({
disableClusteringAtZoom: 1
});
geoJsonLayer = L.geoJson(permData, {
onEachFeature: function (feature, layer) {
var bubble = //Info that goes in marker.
}
});
geoJsonLayer2 = L.geoJson(permData, {
onEachFeature: function (feature, layer) {
var bubble = //Info that goes in marker.
}
});
markers.addLayer(geoJsonLayer);
markers2.addLayer(geoJsonLayer2);
//map.addLayer(markers);
//map.addLayer(markers2);
if (!doGeocode) {
map.fitBounds(markers.getBounds(), { animate: false });
map.fitBounds(markers2.getBounds(), { animate: false });
}
}
and my control function is
function layerControl() {
var lcontrol = L.control.layers({
'Clustered': markers,
'Not Clustered': markers2
}, null, {collapsed: false});
map.addControl(lcontrol);
});
}
I call initLayers when I call $.ajax and return success. After initLayers() I call layerControl(). Am I doing something wrong? Please help !
Fixed it by updating the leaflet version to the latest.

Categories