I am using Leaflet.markercluster.
This is my code, basd upon the various related questions:
// Takes an L.markerClusterGroup as input parameter
Self.GetNumMarkersInClusterGroup = function(clusterGroup)
{
Self.map.eachLayer(function (layer) {
if (layer.getChildCount) {
// somehow need to check here for our desired cluter group
console.log('Cluster group has ' + layer._childClusters.length + 'layers') ;
console.log('With a total of ' + layer._childCount + ' markers');
}
});
} // GetNumMarkersInClusterGroup()
but, layer.getChildCount is undefined :-( What am I doing wrongly?
Related questions:
iterate over cluster in markerCluster : leaflet
Count elements in MarkerCluster
Getting number of clusters and its markers with Leaflet?
Getting the childcount in leaflet markercluster
It is true that there may be some confusion in how to use Leaflet.markercluster plugin:
There is the overall MarkerClusterGroup (MCG) object, i.e. what you get when calling L.markerClusterGroup()
the Cluster Markers, which are what the MCG displays on the map when your individual Markers are clustered together
the individual Markers that you add into an MCG
If your clusterGroup is actually an MCG, then you can simply use the fact that it extends Leaflet standard Feature Group and Layer Group, and in particular it has a getLayers() method:
Returns an array of all the layers added to the group.
So if you want the total number of Markers in your MCG, you can do e.g. clusterGroup.getLayers().length
For completeness, the MCG also has the methods referred to in the Leaflet.markercluster documentation as "group methods"
And the getChildCount() method (and getAllChildMarkers()) is for the Cluster Markers, which are e.g. what you get when using "clusterclick" event and the like.
Related
I'm making a fleet tracker with Mapbox GL JS, it gets the data from a GeoJson and inserts in the map, as the Add live realtime data, I've also integrated the Mapbox store locator example, by now I can update in realtime the sidebar and the points on the map. A modification that I would like to make is not display only one single popup, but a popup for every icon located there. I would like to know how to update this popups, because in the way I'm making it's creating a new popup every movement of the object, but is not closing the previous one. Here is the function that I'm using for the popups
function createPopUp(currentFeature, data) {
var popUps = document.getElementsByClassName('mapboxgl-popup');
//if (popUps[0]) popUps[0].remove();
// mapboxgl.Popup.remove();
if (map.getZoom() > 9) {
var popup = new mapboxgl.Popup({closeOnClick: false})
.setLngLat(currentFeature.geometry.coordinates)
.setHTML('<h3> Aeronave: '+ currentFeature.properties.dev_id + '</h3>' +
'<h4> Curso: ' + currentFeature.properties.curso + 'ยบ<br> Altitude: ' + currentFeature.properties.alt + ' ft<br> Sinal: ' + currentFeature.properties.rssi +'</h4>')
.addTo(map)
.setMaxWidth("fit-content(10px)");
} else{if (popUps[0]) popUps[0].remove()};
}
If I uncomment the popUps[0] line it will only allow 1 popup to be displayed, I've also tried to change dynamically the number between the [] by the number of active tracked devices, it reduced the popup number, but it still repeat some popups of one ID. Also I've tried to change the class name via the .addClasName but it didn't worked.
Thanks
Without seeing how you're calling the createPopUp method in the context of your application, it is difficult to diagnose exactly what is going wrong. I'm not sure why a new popup is being created each time the map moves, so it sounds like you might be calling this method within the Map#on('move') event. That being said, I'm assuming that you're iterating over all of your features and calling the createPopUp method for each in order to initialize all of the popups.
Rather than using an array of DOM nodes generated with var popUps = document.getElementsByClassName('mapboxgl-popup');, I'd recommend specifying a unique and reproducible class name for each feature's popup element when initialized. It looks like each of your features has a dev_id property, so you could do something like:
var popup = new mapboxgl.Popup({closeOnClick: false, className: `mapbox-gl-popup-${dev_id}`})
If you need to change the popup for a particular feature in the future, you can create a helper function to retrieve the relevant DOM node:
function retrievePopUp(feature) {
return document.getElementsByClassName(`mapboxgl-popup-${feature.properties.dev_id}`);
}
I have a layer called "Searched LayerX" having a vector tile source. I am having a simple requirement of highlighting a feature inside this "Searched LayerX" at runtime.
I was thinking of using the result of queryRenderedFeatures on "Searched LayerX" with the filter of unique ID of this particular feature and using this feature's geojson as a separate source to the new layer which I will be adding as "Selected LayerX".
var features = mapBox.queryRenderedFeatures({layers:['Searched LayerX'], filter : ["==",'gid','7818_2_CA']})
var selectedFeature = features[0];
Resultant feature set does not provide any geojson which I can use to create a new geojson source.
So my question is, how do I use the result as a different source to my "Selected LayerX"?
You can use the method described in the first link below - but understand that the returned feature is not the same as the source GeoJSON feature - it is the vector tile representation of that feature at that zoom level, which means it might be highly simplified.
https://gis.stackexchange.com/questions/186533/highlight-feature-with-click-in-mapbox-gl
Another method is to add another layer with the same source, and use the filter function for the highlight as shown in the two links below -
http://www.mapbox.com.s3-website-us-east-1.amazonaws.com/mapbox-gl-js/example/query-similar-features/
highlighting polyline features in mapbox-gl.js
Try this post, I have added the code which will let you have the features using querySourceFeatures() https://stackoverflow.com/a/66308173/9185662
I have already added geojson features to my leaflet map. I want to be able to loop through those geojson features. WHen I do map.eachLayer(function(layer) {...}) it only shows be the tile layer and none of the geojson that are added.
Rather than map.eachLayer, you should be using the .eachLayer method on the L.geoJson itself. For example:
var geoJsonLayer = L.geoJson(myGeoJson).addTo(map);
geoJsonLayer.eachLayer(function(layer) {
layer.bindPopup(layer.feature.properties.name);
});
You can also specify a function to be applied to each feature at the time you create the L.geoJson, using the onEachFeature option.
I am following markercluster examples from Mapbox library, but can't solve my problem. If you guys take a look at my working example here, you will notice this line of code:
L.mapbox.featureLayer(markerLayer).on('ready', function(e) {
What I initally thought was I could put markers inside of markercluster featureLayer, but I guess it was a wrong approach. Any solutions? Thanks.
Example following here
The mapbox example you refer to makes an AJAX call to retrieve the GeoJSON data, hence it needs to attach an on "ready" listener.
In your case your GeoJSON data is defined in your scripts, so the "ready" event will not be triggered (besides, you should use L.mapbox.featureLayer with your GeoJSON object directly, not a Feature Layer).
You can simply use the eachLayer method to iterate through all created markers within the Feature Layer, and add them into your Marker Cluster Group.
var clusterGroup = new L.MarkerClusterGroup();
var markerLayer = L.mapbox.featureLayer(markers).eachLayer(function(layer) {
clusterGroup.addLayer(layer);
});
map.addLayer(clusterGroup);
Updated Plunker: http://plnkr.co/edit/fN6xYcn1Lg532eLe39IS?p=preview
Is it possible to order overlays within the layers control?
Here's my issue. When I do this with my overlays:
var overlays = {
"Apples": apples,
"Bananas": bananas,
"Peaches": peaches
};
L.control.layers(baseLayers, overlays).addTo(map);
Leaflet adds the overlays to the layer control on the map in a random fashion (due to iteration):
- Bananas
- Apples
- Peaches
Is it possible to specificy the order I want to show the overlays? *(In my case, I'd like to have it alphabetical. Also, I am using the Mapbox API)
Thank you.
I am not sure if Mapbox API has changed the default Layers Control code / behaviour, but the latter does not provide a 100% reliable way of displaying overlays in a specific order. See that post for details.
The explanation is that the Layers Control iterates overlays by their "stamp" (a unique identifying integer that is created using L.stamp(myLayer)). Depending on your type of layer, this stamp is assigned automatically but at different moments.
You can force its creation right after having instantiated your layer. For example in your case:
var apples = L.layerGroup();
L.stamp(apples);
var bananas = L.layerGroup();
L.stamp(bananas);
var peaches = L.layerGroup();
L.stamp(peaches);
Unfortunately the order of iteration is not guaranteed as per JS spec, hence the impossibility to have a 100% reliability in this behaviour.
That being said, in all browsers I have tested, the order is in accordance with the natural number order, so as of today, this trick works.
If you want more confidence, you should look for Control plugins that explicitly provide you with the functionality to specify manually the order of listing.