2017-01-31 1 views
1

Ich möchte ein Kreisdiagramm für jeden Punkt auf der Karte anstelle eines Kreises zeichnen. Die Karte und die Punkte werden gut angezeigt, aber das Kreisdiagramm wird nicht über die Kartenpunkte angezeigt. Es gibt auch keinen Fehler. Ich kann den hinzugefügten Kreisdiagrammcode auch innerhalb der Karte sehen.Kreisdiagramm über einen Kartenpunkt mit d3.js

Unten ist das Code-Snippet.

var w = 600; 
var h = 600; 
var bounds = [[78,30], [87, 8]]; // rough extents of India 
var proj = d3.geo.mercator() 
     .scale(800) 
     .translate([w/2,h/2]) 
     .rotate([(bounds[0][0] + bounds[1][0])/-2, 
      (bounds[0][1] + bounds[1][1])/-2]); // rotate the project to bring India into view. 

var path = d3.geo.path().projection(proj); 

var map = d3.select("#chart").append("svg:svg") 
     .attr("width", w) 
     .attr("height", h); 

var india = map.append("svg:g") 
     .attr("id", "india"); 

var gDataPoints = map.append("g"); // appended second 
d3.json("data/states.json", function(json) { 
    india.selectAll("path") 
      .data(json.features) 
      .enter().append("path") 
      .attr("d", path); 

}); 

d3.csv("data/water.csv", function(csv) { 
    console.log(JSON.stringify(csv)) 
    gDataPoints.selectAll("circle") 
      .data(csv) 
      .enter() 
      .append("circle") 
      .attr("id", function (d,i) { 
       return "chart"+i; 
      }) 
      .attr("cx", function (d) { 
       return proj([d.lon, d.lat])[0]; 
      }) 
      .attr("cy", function (d) { 
       return proj([d.lon, d.lat])[1]; 
      }) 
      .attr("r", function (d) { 
       return 3; 
      }) 
      .each(function (d,i) { 
       barchart("chart"+i); 
      }) 
      .style("fill", "red") 
      //.style("opacity", 1); 
}); 


function barchart(id){ 

    var data=[15,30,35,20];  
    var radius=30; 
    var color=d3.scale.category10()   

    var svg1=d3.select("#"+id) 
      .append("svg").attr('width',100).attr('height',100); 

    var group=svg1.append('g').attr("transform","translate(" + radius + "," + radius + ")"); 
    var arc=d3.svg.arc() 
      .innerRadius('0') 
      .outerRadius(radius); 
    var pie=d3.layout.pie() 
      .value(function(d){ 
       return d; 
      }); 

    var arcs=group.selectAll(".arc") 
      .data(pie(data)) 
      .enter() 
      .append('g') 
      .attr('class','arc') 

    arcs.append('path') 
      .attr('d',arc) 
      .attr("fill",function(d,i){ 
       return color(d.data); 
       //return colors[i] 
      }); 
} 

water.csv:

lon,lat,quality,complaints 
80.06,20.07,4,17 
72.822,18.968,2,62 
77.216,28.613,5,49 
92.79,87.208,4,3 
87.208,21.813,1,12 
77.589,12.987,2,54 
16.320,75.724,4,7 

Antwort

1

in Ihrem Code zu testen ich nicht in der Lage war, die Tortendiagramme Rendering, um zu sehen, überhaupt nicht. Aber ich glaube, ich habe immer noch eine Lösung für dich.

Sie benötigen keine separate Kreisdiagrammfunktion, um jeden Punkt aufzurufen. Ich bin sicher, dass es eine Vielzahl von Meinungen dazu gibt, aber d3 Fragen zu Stack Overflow rufen oft zusätzliche Funktionen hervor, die den Code verlängern, während die Stärken von d3 und die eingebauten Funktionen nicht genutzt werden.

Warum fühle ich mich so in diesem Fall? Es ist schwierig, die Verbindung zwischen Daten, die an SVG-Objekte gebunden sind, und Ihrer Tortendiagrammfunktion beizubehalten. Aus diesem Grund müssen Sie die ID des Punkts an Ihre Funktion übergeben. Dies wird komplementiert, wenn Sie Tortendiagrammdaten in Ihrem CSV selbst haben möchten.

Mit der Datenbindung und Auswahl von d3 können Sie alles tun, was Sie brauchen, mit viel einfacherem Code. Es hat einige Zeit gedauert, bis ich herausgefunden hatte, wie man das macht, aber es macht das Leben einfacher, sobald man den Dreh raus hat.

Hinweis: Ich entschuldige mich, ich portierte den Code, den Sie auf d3v4 gepostet haben, aber ich habe einen Link zum d3v3-Code, sowie d3v4, obwohl in den Schnipsel die einzige offensichtliche Änderung enthalten sein kann Farbe (i) bis Farbe [i]


In diesem Fall eher als eine Funktion aufrufen, Tortendiagramme zu jedem circle Element mit selection.each() anhängen, können wir eine g Element statt und dann Elemente anhängen direkt anhängen jeweils g mit Auswahlen. Wenn wir zu Beginn jedes Element g mit einer Transformation verknüpfen, können wir relative Messungen verwenden, um Elemente in jedem g zu platzieren, anstatt die absoluten svg-Koordinaten herauszufinden, die wir sonst benötigen würden.

Nun, was wäre, wenn wir Daten von der CSV für jedes Tortendiagramm zeigen und vielleicht ein Etikett hinzufügen möchten. Dies ist jetzt ganz einfach erledigt. Im csv, wenn es eine Spalte data mit Werten getrennt durch einen Bindestrich und eine Spalte mit dem Namen label gekennzeichnet war, konnten wir unseren Code leicht anpassen diese neuen Daten zeigen:

d3.csv("water.csv", function(error, water) { 

    var points = gDataPoints.selectAll("g") 
     .data(water) 
     .enter() 
     .append("g") 
     .attr("transform",function(d) { return "translate("+projection([d.lon,d.lat])+")" }) 
     .attr("class","pies") 

    points.append("text") 
     .attr("y", -radius - 5) 
     .text(function(d) { return d.label }) 
     .style('text-anchor','middle'); 

    var pies = points.selectAll(".pies") 
     .data(function(d) { return pie(d.data.split(['-'])); }) 
     .enter() 
     .append('g') 
     .attr('class','arc'); 

    pies.append("path") 
     .attr('d',arc) 
     .attr("fill",function(d,i){ 
      return color[i];  
     }); 

}); 

Die Daten, die wir anzeigen möchten ist bereits an die ursprüngliche g gebunden, die wir für jede Zeile in der CSV erstellt haben. Jetzt müssen wir nur noch die anzuzeigenden Elemente anfügen und auswählen, welche Eigenschaften der gebundenen Daten angezeigt werden sollen.

Das Ergebnis in diesem Fall wie folgt aussieht:

enter image description here

I Beispiele in v3 und v4 gepostet habe eine potentielle Implementierung zu zeigen, dass für die Tortendiagramme den oben beschriebenen Ansatz folgt:

Mit ein statisches Datenfeld für alle Kreisdiagramme wie im Beispiel: v4 und v3

Und durch Ziehen von Daten aus dem CSV zur Anzeige: v4 und v3

+0

Auch können Sie einige Probleme mit den CSV-Werten haben: '16.320,75.724' ist nicht in Indien, wenn das ein Längengrad-Breiten-Paar ist. Es gibt auch: '92.79, 87.208' –

+1

Und weil es Spaß gemacht hat, Kreisdiagramme auf Karten in d3 zu betrachten, habe ich einen sehr kurzen Blick auf eine mögliche Implementierung der Verwendung von Klickereignissen geworfen, um das Kreisdiagramm an einem Datenpunkt zu zeigen. Es wird sicherlich bessere Implementierungen geben, aber hier ist eine: https://bl.ocks.org/Andrew-Reid/6efd12c6bcfe9a044750e81dbc3497f4 –