2016-09-20 3 views
3

Ich bin ein Datenjournalist versucht meine Hand bei d3 v4 zum ersten Mal, um eine Kraft-Layout, Beziehungen zwischen Bands mit Daten aus der Spotify API zu erstellen. Ich begann mit dem Beispiel von Mike Bostock (https://bl.ocks.org/mbostock/4062045). Ich änderte den Code jedes svg Kreis Element in einem „g“ Element zu wickeln:Ziehen Knoten mit Etiketten in d3 v4 zwingen Layout-Glitches

var link = svg.append("g").attr("class", "links") 
      .selectAll("line") 
      .data(graph.links) 
      .enter().append("line") 
       .attr("stroke-width", function(d) { return Math.sqrt(d.value); }); 
var gnodes = svg.selectAll("g.gnode") 
      .data(graph.nodes) 
      .enter() 
      .append("g") 
      .classed("gnode", true); 
var node = gnodes.append("circle") 
      .attr("class", "nodes") 
      .attr("r", 5) 
      .style("fill", function(d) { return color(d.group); }) 
      .call(d3.drag() 
       .on("start", dragstarted) 
       .on("drag", dragged) 
       .on("end", dragended)); 

Danach tun, erstelle ich den Titel und die Kennzeichnungselemente und hängen Sie sie an den Knoten:

gnodes.append("title").text(function(d) { return d.label }); 
var labels = gnodes.append("text").text(function(d) { return d.label; }); 
labels.attr("transform", function(d) { 
    return "translate(" + (d.x) + "," + (d.y) + ")"; 
}); 

Schließlich Ich habe die Funktion ticked() modifiziert, um (hoffentlich) zu ermöglichen, dass sich die Etiketten bewegen, wenn die Knoten gezogen werden. Sie können durch den Kommentar, den ich gemacht habe, sehen, dass ich bereits versucht habe, die Methode auf jedes circle svg-Element anstelle des Gruppenelements anzuwenden, aber offensichtlich nicht funktioniert hat. Ich bin mir auch nicht sicher, ob die letzte Zeile tatsächlich etwas Nützliches tut.

function ticked() { 
    link 
     .attr("x1", function(d) { return d.source.x; }) 
     .attr("y1", function(d) { return d.source.y; }) 
     .attr("x2", function(d) { return d.target.x; }) 
     .attr("y2", function(d) { return d.target.y; }); 
    gnodes 
    //node 
     .attr("transform", function(d) { 
      return "translate(" + [d.x, d.y] + ")";}); 
    labels.attr("transform", function(d) { return "translate(" + (d.x) + "," + (d.y) + ")"; }); 
} 

Das Problem ist, dass, obwohl die Etiketten korrekt angezeigt bekommen, wenn ein Knoten die Knoten „Glitches“ gezogen wird und verhält sich nicht richtig, wahrscheinlich weil das Etikett irgendwie verwirrt oder etwas wird immer und sie sind nicht sozusagen "synchron".

ich bereits bei this example geschaut haben, auch von Mike Bostock und this one von Moritz Stefaner, haben aber nicht in der Lage gewesen, eine geeignete Lösung (diese beiden sind d3 v3 Code zu implementieren, soweit ich weiß, didn Hilf mir nicht viel.

Der vollständige Code für die HTML-Seite ist in diesem Pastebin verfügbar: http://pastebin.com/qw9bYHRD und, wenn für eine Art von Tests erforderlich, die JSON-Datei, die ich verwenden, um das Netzwerkdiagramm zu generieren, ist verfügbar unter this address.

Es tut mir leid für meine schlechten Kenntnisse von d3, aber dies ist einer meiner ersten tiefen Tauchgänge in die Bibliothek (auch das erste Mal mit v4), nachdem ich einige andere Tools für einige Zeit verwendet habe.

Vielen Dank im Voraus für Ihre Zeit und Aufmerksamkeit.

Antwort

2

Okay, scheint alles zu schreiben, was mir geholfen hat zu denken und ich habe es geschafft, dieses Problem selbst zu lösen. Die Antwort hier eingeben für den Fall, dass jemand das gleiche Problem hat.

Die sehr einfache Lösung hat mit dem Objekt zu tun, auf dem die .call(d3.drag()) ausgeführt wird. I geschnitten dieses Stück Code aus dem Knotenvariable (die circle SVG-Elemente), und es am Ende der Variablen eingefügt, die die g SVG Elemente definiert:

.call(d3.drag() 
    .on("start", dragstarted) 
    .on("drag", dragged) 
    .on("end", dragended)); 

So die g Elemente Erklärung wie diese endet:

var gnodes = svg.selectAll("g.gnode") 
    .data(graph.nodes) 
    .enter() 
    .append("g") 
    .classed("gnode", true) 
    .call(d3.drag() 
     .on("start", dragstarted) 
     .on("drag", dragged) 
     .on("end", dragended)); 

Und es funktioniert von da an richtig. Sie können sogar nur die Beschriftung ziehen, und der Knoten folgt ihr auf der Zeichenfläche. Groß!