2016-05-26 23 views
1

In meiner Webanwendung AngularJs baue ich eine Karte mit Leaflet.js und Leaflet markercluster.Einfügen von NVD3-Chart in Leaflet-Popup

Charts zu machen ich nvd3.js und die nvd3-angular-directive

Ich habe verschiedene Daten kommen aus der ganzen Welt verwendet, und ich bin eine einfache CircleMarker für jede Nation zeigt, die Daten empfangen hat.

sind meine Daten auf diese Weise organisiert:

{ 
    US : {country:"US", count:10, rate: {high: 3, medium: 4, low: 3}}, 
    IT : {country:"IT", count:4, rate: {high: 1, medium: 1, low: 2}} 
} 

Das bedeutet, dass ein CircleMarker in der Karte wird in der Mitte der USA und Italien gezeigt werden.

Jetzt ist auf die Frage erhalten lassen, ich bin ein Pop-up auf jeder CircleMarker Bindung, möchte ich jedes Popup eine nvd3 Kuchen enthalten (insbesondere ein Donut) Diagramm, das die Verteilung der rate s für diese bestimmte Nation zeigen.

Das Problem ist, dass derzeit die Karte richtig gerendert wird und die Marker perfekt platziert sind, aber wenn ich auf eine Markierung klicke, ist das Popup, das erscheint, leer (siehe Abbildung). Ich habe gegoogelt, konnte aber nichts finden, was mir helfen könnte.

Empty Popup


Dies ist, wie ich die CircleMarkers und den Cluster bauen:

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

Ich habe änderten sich die Dinge ein wenig. Zum einen habe ich erweitert die CircleMarker Klasse

var customCircleMarker = L.CircleMarker.extend({ 
    options: { 
    countrycode: '', 
    rates: {}, 
    count: 0 
    } 
}) 

Dann benutze ich diese CustomCircleMarker in meiner Karte

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] 
}] 

Dann habe ich das Popup binden, füllen Sie den Marker mit meiner benutzerdefinierten Daten und erstellen ein auf click Rückruf die gibt eine Nachricht mit meinen nützlichen Daten aus.

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) 
}) 

Der Empfänger wird die Daten und machen Sie das Diagramm auf diese Weise nehmen:

$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; 
    }) 
}) 

Leider ist dies nicht wieder zu arbeiten .. not working again

HINWEIS: Ich bin nicht Ich benutze die eckige-Prospekt-Anweisung, weil ich es ziemlich übertrieben fand und es nicht so sehr mochte. Denkst du, es ist besser für mich, es trotzdem zu benutzen?

Antwort

1

Ich habe das Problem selbst gelöst, ich schreibe eine Antwort, da es für zukünftige Benutzer hilfreich sein könnte.

Das Wichtigste, was ich vergessen ein <svg> Element innerhalb des Popup einzufügen war, dies das Diagramm nicht gerendert wird verursacht, da es keine ‚Leinwand‘ waren sind wir die Bibliothek es machen könnte ..

Marker-Generation:

var marker = new customCircleMarker(countries.names[c].latlng, {stroke: false, className: 'the-class-name', fillOpacity: 1, weight: 1}) 

marker.bindPopup('<div id="chart-' + key + '" class="country-popup-chart-container"><svg class="country-popup-chart"></svg></div>', {closeButton: false}) 
marker.countrycode = key 
marker.rates = geolocLoad[key].rate 
marker.count = geolocLoad[key].count 

marker.on('click', function(e){ 
    $scope.$emit('marker:click', this.countrycode, this.count, this.rates) 
}) 

Diagramm Generation ausgelöst mit einem $emit aufgerufen auf click:

$scope.$on('marker:click', function(caller, countrycode, count, rates) { 

    var popupChartData = [{ 
    label: 'low', 
    value: rates.low, 
    color: '#2ecc71' 
    }, { 
    label: 'medium', 
    value: rates.medium, 
    color: '#f1c40f' 
    }, { 
    label: 'high', 
    value: rates.high, 
    color: '#e74c3c' 
    }] 

    nv.addGraph(function(){ 
    var chart = nv.models.pieChart() 
     .x(function(d) { return d.label }) 
     .y(function(d) { return d.value }) 
     .showLabels(false) 
     .donut(true) 
     .donutRatio(0.5) 

    d3.select('#chart-' + countrycode + ' svg') 
     .datum(popupChartData) 
     .call(chart) 

    return chart 
    }) 
}) 

Sized up mit folgendem CSS:

div.country-popup-chart-container{ 
    height: 80px; 
    width: 200px; 
} 

Das Endergebnis ist:

final result