2013-05-14 11 views
8

Ich habe eine ziemlich einfache Visualisierung, die ich zusammensetzen möchte, aber mit einem kleinen Problem bei der Verarbeitung.Warum wird das erste Link-Objekt übersprungen?

Wenn ich die folgenden Schnipsel dann funktioniert alles wie erwartet:

var lines = svg.selectAll("line") 
         .data(data.links) 
         .enter() 
         .append("svg:line") 
          .attr("x1", function(d) { return findNode(data.nodes, d.source).x;}) 
          .attr("y1", function(d) { return findNode(data.nodes, d.source).y;}) 
          .attr("x2", function(d) { return findNode(data.nodes, d.target).x;}) 
          .attr("y2", function(d) { return findNode(data.nodes, d.target).y;}) 
          .style("stroke", "#838383") 
          .style("stroke-width", 1) 
          .style("marker-end", "url(#end-arrow)"); 

Wenn ich schalte dies jedoch ein etwas anderes zu verwenden, Wege mit:

var paths = svg.selectAll("path") 
         .data(data.links) 
         .enter() 
         .append("svg:path") 
          .attr("d", function(d) { 
           debugger; 
           var src = findNode(data.nodes, d.source); 
           var tgt = findNode(data.nodes, d.target); 
           var xi = d3.interpolateNumber(src.x, tgt.x); 
           var curvature = 0.8; 

           return "M" + src.x + "," + src.y 
            + "C" + xi(curvature) + "," + src.y 
            + " " + xi(1 - curvature) + "," + tgt.y 
            + " " + tgt.x + "," + tgt.y; 
          }) 
          .style("stroke", "#838383") 
          .attr("fill", "none"); 

Dann aus irgendeinem Grunde des erster 'Link' fehlt. Kann jemand vorschlagen, warum das sein könnte? Es gibt ein JSFiddle here. Der Effekt, der erwartet wird, ist, dass ich keine schönen abgerundeten Linien habe, wie ich es möchte.

Antwort

10

Das Problem ist, dass D3 Ihre Auswahl .selectAll("path") zu Ihren Daten per Index standardmäßig entspricht und es gibt bereits einen Pfad im SVG (in defs). Das heißt, das erste Datenelement stimmt mit dem ersten Pfad im SVG überein, der bereits vorhanden ist. Daher ist es nicht in der .enter() Auswahl.

Die Art und Weise, dies zu beheben, besteht darin, eine Funktion in dem optionalen zweiten Argument .data() anzugeben, um D3 mitzuteilen, wie Elemente, z.B.

.data(data.links, function(d, i) { return d + i; }) 
+0

Brilliant - ich hätte das nie gefunden. Als Extra wissen Sie, ob es eine einfache Möglichkeit gibt, Pfeile auf Beziers zu bekommen. Meine vertikalen Markierungen fehlen ... – Ian

+0

Entschuldigung, nicht von meinem Kopf ... –

Verwandte Themen