Presenting High Level Information With PruneCluster and LeafletJS
How to express high level information using clusters in LeafletJS.
Join the DZone community and get the full member experience.
Join For FreeWe've already done some basics with PruneCluster and LeafletJS, and then added in an area selection tool. There's one last part to this trilogy - showing information effectively using clusters and categories.
The default clustering provided by PruneCluster is really good, but if you're looking from a high level it can be difficult to see what each cluster is comprised of. For a refresher, here's the default view:
Luckily, PruneCluster is extremely configurable - even down to the level of what icons are drawn up at the cluster level. You can see a good implementation of this in the list of project examples
First, it's a good idea to add categories to each of your markers. For performance reasons, the authors of PruneCluster recommend that you use numbers for categories.
//define a set of categories
var TECH_COMPANY_CATEGORY = 0;
var FINANCIAL_COMPANY_CATEGORY = 1;
//...
//then attach categories to markers as you go
marker.category = TECH_COMPANY_CATEGORY;
The index of the category will be important later, as it will determine the color to be used. Each MarkerCluster has a number of properties and functions that help you to customise the look and feel
L.Icon.MarkerCluster = L.Icon.extend({
options: {
},
createIcon: function() {
},
createShadow: function() {
},
draw: function(canvas, width, height) {
}
});
The full listing, taken straight from the example from PruneCluster's project follows.
Some important points:
The list of colors will match the category. So, any marker with category 0 (TECH_COMPANY_CATEGORY) will get colors[0] assigned to it:
var colors = ['#ff00b4', '#ff4b00', '#00ff4b', '#00b4ff'],
pi2 = Math.PI * 2;
L.Icon.MarkerCluster = L.Icon.extend({
options: {
iconSize: new L.Point(44, 44),
className: 'prunecluster leaflet-markercluster-icon'
},
createIcon: function() {
// based on L.Icon.Canvas from shramov/leaflet-plugins (BSD licence)
var e = document.createElement('canvas');
this._setIconStyles(e, 'icon');
var s = this.options.iconSize;
e.width = s.x;
e.height = s.y;
this.draw(e.getContext('2d'), s.x, s.y);
return e;
},
createShadow: function() {
return null;
},
draw: function(canvas, width, height) {
var lol = 0;
var start = 0;
for (var i = 0, l = colors.length; i < l; ++i) {
var size = this.stats[i] / this.population;
if (size > 0) {
canvas.beginPath();
canvas.moveTo(22, 22);
canvas.fillStyle = colors[i];
var from = start + 0.14,
to = start + size * pi2;
if (to < from) {
from = start;
}
canvas.arc(22, 22, 22, from, to);
start = start + size * pi2;
canvas.lineTo(22, 22);
canvas.fill();
canvas.closePath();
}
}
canvas.beginPath();
canvas.fillStyle = 'white';
canvas.arc(22, 22, 18, 0, Math.PI * 2);
canvas.fill();
canvas.closePath();
canvas.fillStyle = '#555';
canvas.textAlign = 'center';
canvas.textBaseline = 'middle';
canvas.font = 'bold 12px sans-serif';
canvas.fillText(this.population, 22, 22, 40);
}
});
With this defined, you will just need to register all clusters in a particular PruneCluster to be drawn with this specification:
cluster.BuildLeafletClusterIcon = function(cluster) {
var e = new L.Icon.MarkerCluster();
e.stats = cluster.stats;
e.population = cluster.population;
return e;
};
The stats and population project are provided by PruneCluster by default. Now, rather than an overview number, you also see the ratio of each category of marker to others within the cluster:
By adding in a legend on your page for each of the colors, this can be very powerful.
Opinions expressed by DZone contributors are their own.
Comments