2016-07-01 3 views
2

Ich erstelle ein paralleles Koordinaten-Diagramm. Jeder Kreis ist eine besondere Marke, und jede Marke hat einen Kreis in jeder Spalte:D3 - Zeichnen eines Pfades zwischen DOM-Elementen

enter image description here

Wenn der Benutzer über einen Kreis schwebt, würde Ich mag einen Pfad zeichnen diesen Kreis zu den anderen drei Kreisen der Verbindungs die gleiche Marke. Das Problem ist, dass die X-Position der Kreise zufällig ist, also muss ich die Linie mit dem modifizierten cx-Wert des Kreises zeichnen (und nicht mit den Daten).

Günstig, ich habe alle in ihren eigenen g Elemente gruppiert vier Marke Kreise:

<g class="line-group"> 
    <circle r="5" cx="340.48700997553686" cy="0" data-brand="Brand X"></circle> 
    <circle r="5" cx="916.9181438059958" cy="59.347826086956466" data-brand="Brand X"></circle> 
    <circle r="5" cx="1589.2772695723352" cy="229.1306884480747" data-brand="Brand X"></circle> 
    <circle r="5" cx="2272.275506967826" cy="0" data-brand="Brand X"></circle> 
</g> 

ich die Elemente greifen kann, und gruppieren Sie die Koordinaten in einer Art und Weise d3.line() mag, aber es macht einen Linie, die jeden Punkt verbindet.

var line = d3.svg.line() 
       .interpolate('basis'); 

var circles = d3.selectAll('.line-group').selectAll('circle'), 
      circleCoords = []; 

     circles.forEach(function(d) { 
     console.log(circles); 
     for (i = 0; i < d.length; i++) { 
      var cx = d3.select(d[i]).attr('cx'), 
       cy = d3.select(d[i]).attr('cy'); 

      circleCoords.push([cx, cy]); 
     } 
     }); 

     lineGroup.append('path') 
      .attr({ 
       'd' : line(circleCoords) 
      }); 

Wie strukturiere ich dies so kann ich die Werte cx und cy jeden Kreis Gruppe greifen (die vier Kreise der gleichen Marke innerhalb von g.line-Gruppe)?

Ich muß wahrscheinlich ein benutzerdefinierten d Attribut, so etwas wie dieser (Pseudo-Code):

path.attr('d', function(d) { 
        return 'M ' + /* cx of circle 1 */ + ' ' + /* cy of circle 1 */ + 
        ' L ' + /* cx of circle 2 */ + ' ' + /* cy of circle 2 */ + 
        ' L ' + /* cx of circle 3 */ + ' ' + /* cy of circle 3 */ + 
        ' L ' + /* cx of circle 4 */ + ' ' + /* cy of circle 4 */ + ' Z'; 
       }) 

Ich glaube, dass alle Teile da sind, ich kann einfach nicht scheinen, einen Weg zu finden, um es zusammen zu setzen korrekt. Wenn jemand irgendwelche Ideen hat, würde es sehr geschätzt werden!

Bearbeiten: Linedefinition hinzugefügt.

Antwort

2

Sie hat die falsche Auswahl (ich kann nicht Ihre Liniendefinition sehen, vergessen Sie es nicht):

var svg = d3.selectAll("svg") 
var circles = svg.selectAll('.line-group').selectAll("circle"), 
// or var circles = svg.selectAll('.line-group > circle'), 

      circleCoords = []; 

     circles.forEach(function(d) { 
     for (i = 0; i < d.length; i++) { 
      var cx = d3.select(d[i]).attr('cx'), 
       cy = d3.select(d[i]).attr('cy'); 

      circleCoords.push([cx, cy]); 
     } 
     console.log(circleCoords); 
     }); 

     var line = d3.svg.line() 

     svg.append('path') 
      .attr({ 
       'd' : line(circleCoords) 
      }); 

Here the working code

Nicht Stile vergessen. Sie müssen jede '.line-Gruppe identifizieren oder D3 wählt alle ‚.line-Gruppe‘ Klasse, kann das Hinzufügen id attribute.-

In Ihrem Fall, dass Sie mehrere ‚Marken‘ haben, etwa so:

<svg> 
<g class="line-group"> 
    <circle r="5" cx="10" cy="110" data-brand="Brand-X"></circle> 
    <circle r="5" cx="30" cy="120" data-brand="Brand-X"></circle> 
    <circle r="5" cx="150" cy="30" data-brand="Brand-X"></circle> 
    <circle r="5" cx="290" cy="40" data-brand="Brand-X"></circle> 
</g> 

<g class="line-group"> 
    <circle r="5" cx="10" cy="10" data-brand="Brand-Y"></circle> 
    <circle r="5" cx="30" cy="20" data-brand="Brand-Y"></circle> 
    <circle r="5" cx="150" cy="130" data-brand="Brand-Y"></circle> 
    <circle r="5" cx="290" cy="140" data-brand="Brand-Y"></circle> 
</g> 
</svg> 

Sie müssen Ihren Code Refactory:

var svg = d3.selectAll("svg") 
var circles = svg.selectAll('.line-group').selectAll("circle"), 
      circleCoords = []; 
var line = d3.svg.line() 

// circles.length give you .line-group's count or brand's count: 

    for (j=0; j<circles.length; j++) { 
     circles[j].forEach(function(d) {  // forEach brand draw a line 
      var cx = d.getAttribute('cx'), 
       cy = d.getAttribute('cy'); 
      circleCoords.push([cx, cy]); 
     }) 
     svg.append('path') 
      .attr({ 'd' : line(circleCoords) }) 
      .attr("id","id_"+j); 
     circleCoords = []; 
    }; 

Here's the working code

+0

Wenn ich eine zweite Linie-Gruppe (Marke Y) hinzufügen, das schafft nur einen Pfad (alle cir Verbindungs cles für Marke X und Marke Y zusammen). Wie kann ich es so machen, dass Brand X und Brand Y jeweils eigene Linien haben? Siehe Geige: https://jsfiddle.net/uobpp0La/7/ – BastionGamma

+0

Yeap. Sie müssen immer noch die richtige Serie auswählen. Deshalb muss für jede Serie eine eindeutige ID definiert werden. Sie könnten das Datenmarkenattribut – Klaujesi

+0

verwenden. Wie würden Sie das empfehlen? Ich versuche etwas wie: 'var allBrandIDs = d3.set (studyData.map (Funktion (d) {return d.brand_id;})) .values ​​();' und dann 'allBrandIDs.forEach (Funktion (d) { var circles = $ ('circle'). find ("[datenmarke = '" + d +' '] ");});' – BastionGamma