My AngularJs web application incorporates a map built with Leaflet.js and Leaflet markercluster. For rendering charts, I utilize nvd3.js along with the nvd3-angular-directive.
The data I have represents various countries worldwide, each displayed on the map as a CircleMarker based on the data structure below:
{
US : {country:"US", count:10, rate: {high: 3, medium: 4, low: 3}},
IT : {country:"IT", count:4, rate: {high: 1, medium: 1, low: 2}}
}
This indicates that a CircleMarker will be shown at the center of the USA and Italy in the map.
The main challenge arises when I attempt to bind a popup containing an nvd3 pie (specifically a donut) chart for each respective nation's rate distribution upon clicking on the CircleMarker. Despite the markers displaying correctly on the map, the popups appear empty when clicked.
Here is my approach to building the CircleMarkers and clusters:
var markers = L.markerClusterGroup({
maxClusterRadius: 120,
iconCreateFunction: function (cluster) {
return L.divIcon({html: '<b>' + cluster.getChildCount() + '</b>', className: 'mycluster', iconSize: L.point(40, 40)});
}
})
var geolocData = {
US : {country:"US", count:10, rate: {high: 3, medium: 4, low: 3}},
IT : {country:"IT", count:4, rate: {high: 1, medium: 1, low: 2}}
}
for (key in geolocData){
var latlng = retrieveLatLongFromCountryCode(key)
var marker = new L.circleMarker(latlng, {stroke: false, className:'the-marker-class', fillOpacity: 1, color:'#00FF00', weight: 1})
var popupChartOptions = {
chart: {
type: 'pieChart',
height: 140,
donut: true,
donutRatio: 0.40,
x: function(d) { return d.label },
y: function(d) { return d.value },
color: [
'#2ecc71',
'#f1c40f',
'#e74c3c',
],
valueFormat: d3.format(',.0d')
}
}
var popupChartData = [{
label: 'low',
value: geolocData[key].rate.low
}, {
label: 'medium',
value: geolocData[key].rate.medium
}, {
label: 'high',
value: geolocData[key].rate.high
}]
marker.bindPopup('<nvd3 options="chartOptions" data="chartData"></nvd3>')
markers.addLayers(marker)
}
map.addLayer(markers)
UPDATE
I've made adjustments by extending the CircleMarker class:
var customCircleMarker = L.CircleMarker.extend({
options: {
countrycode: '',
rates: {},
count: 0
}
})
Subsequently, I implement this CustomCircleMarker within my map:
var marker = new customCircleMarker(latlng, {stroke: false, className: 'the-class-name', fillOpacity: 1, weight: 1})
var popupChartData = [{
label: 'low',
value: [geolocLoad[key].rate.low]
}, {
label: 'medium',
value: [geolocLoad[key].rate.medium]
}, {
label: 'high',
value: [geolocLoad[key].rate.high]
}]
Then, I bind the popup, populate the marker with custom data, and establish an on click callback which emits relevant information:
marker.bindPopup('<div id="chart-' + key + '"></div>')
marker.countrycode = key
marker.rates = popupChartData
marker.count = geolocLoad[key].count
marker.on('click', function(e){
$scope.$emit('marker:click', this.countrycode, this.count, this.rates)
})
The receiver processes the data and renders the chart accordingly:
$scope.$on('marker:click', function(caller, countrycode, count, rates){
console.log('received', countrycode, count, rates)
var width = 500,
height = 500
nv.addGraph(function(){
var chart = nv.models.pieChart()
.x(function(d) { return d.label })
.y(function(d) { return d.value })
.width(width)
.height(height);
d3.select("#chart-"+countrycode)
.datum(rates)
.attr('width', width)
.attr('height', height)
.call(chart);
return chart;
})
})
Unfortunately, this revised approach is still not yielding desired results. https://i.sstatic.net/0oHDK.png
NOTE: I opted against using the angular-leaflet-directive due to personal preference. Do you believe it would be beneficial for me to reconsider utilizing it?