PruneCluster is a fast and realtime marker clustering library.
It's working with Leaflet as an alternative to Leaflet.markercluster.
The library is designed for large datasets or live situations. The memory consumption is kept low and the library is fast on mobile devices, thanks to a new algorithm inspired by collision detection in physical engines.
Features
Realtime
The clusters can be updated in realtime. It's perfect for live situations.
Fast
Number of markers | First step | Update (low zoom level) | Update (high zoom level) |
---|---|---|---|
100 | instant | instant | instant |
1 000 | instant | instant | instant |
10 000 | 14ms | 3ms | 2ms |
60 000 | 70ms | 23ms | 9ms |
150 000 | 220ms | 60ms | 20ms |
1 000 000 | 1.9s | 400ms | 135ms |
These values are tested with random positions, on a recent laptop, using Chrome 38. One half of markers is moving randomly and the other half is static. It is also fast enough for mobile devices.
If you prefer real world data, the 50k Leaflet.markercluster example is computed in 60ms (original).
Weight
You can specify the weight of each marker.
For example, you may want to add more importance to a marker representing an incident, than a marker representing a tweet.
Categories
You can specify a category for the markers. Then a small object representing the number of markers for each category is attached to the clusters. This way, you can create cluster icons adapted to their content.
Dynamic cluster size
The size of a cluster can be adjusted on the fly (Example)
Filtering
The markers can be filtered easily with no performance cost.
Usage
var pruneCluster = new PruneClusterForLeaflet();
...
var marker = new PruneCluster.Marker(latitude, longitude);
pruneCluster.RegisterMarker(marker);
...
leafletMap.addLayer(pruneCluster);
Update a position
marker.Move(lat, lng);
Deletions
// Remove all the markers
pruneCluster.RemoveMarkers();
// Remove a list of markers
pruneCluster.RemoveMarkers([markerA,markerB,...]);
Set the category
The category can be a number or a string, but in order to minimize the performance cost, it is recommended to use numbers between 0 and 7.
marker.category = 5;
Set the weight
marker.weight = 4;
Filtering
marker.filtered = true|false;
Set the clustering size
pruneCluster.Cluster.Size = 87;
Apply the changes
Must be called when ANY changes are made.
pruneCluster.ProcessView();
Add custom data to marker object
Each marker has a data object where you can specify your data.
marker.data.name = 'Roger';
marker.data.ID = '76ez';
Setting up a Leaflet icon or a Leaflet popup
You can attach to the markers an icon object and a popup content
marker.data.icon = L.icon(...); // See http://leafletjs.com/reference.html#icon
marker.data.popup = 'Popup content';
Faster leaflet icons
If you have a lot of markers, you can create the icons and popups on the fly in order to improve their performance.
function createIcon(data, category) {
return L.icon(...);
}
...
marker.data.icon = createIcon;
You can also override the PreapareLeafletMarker method. You can apply listeners to the markers here.
pruneCluster.PrepareLeafletMarker = function(leafletMarker, data) {
leafletMarker.setIcon(/*... */); // See http://leafletjs.com/reference.html#icon
//listeners can be applied to markers in this function
leafletMarker.on('click', function(){
//do click event logic here
});
// A popup can already be attached to the marker
// bindPopup can override it, but it's faster to update the content instead
if (leafletMarker.getPopup()) {
leafletMarker.setPopupContent(data.name);
} else {
leafletMarker.bindPopup(data.name);
}
};
Setting up a custom cluster icon
pruneCluster.BuildLeafletClusterIcon = function(cluster) {
var population = cluster.population, // the number of markers inside the cluster
stats = cluster.stats; // if you have categories on your markers
// If you want list of markers inside the cluster
// (you must enable the option using PruneCluster.Cluster.ENABLE_MARKERS_LIST = true)
var markers = cluster.getClusterMarkers()
...
return icon; // L.Icon object (See http://leafletjs.com/reference.html#icon);
};
Redraw the icons
Marker icon redrawing with a flag:
marker.data.forceIconRedraw = true;
...
pruneCluster.ProcessView();
Redraw all the icons:
pruneCluster.RedrawIcons();
Acknowledgements
This library is developed in context of the BRIDGE project.
Licence
The source code of this library is licenced under the MIT License.