2017-02-09 2 views
0

Ich bin sehr neu in D3 passiert, Ich versuche, eine einfache Live-Chart lose auf einem Ausschnitt aus hier basiert zu machen: https://bost.ocks.org/mike/path/D3 Übergangslinie zweimal

ich in der Lage sein wollen, eine Reihe von Linien zu einem hinzufügen Live-Chart verschieben und von einem Web-Socket aktualisieren lassen (ich weiß, wie man das Bit macht!)

Wenn ich versuche, eine zweite Zeile hinzuzufügen, wird das Diagramm nicht reibungslos aktualisiert, ich denke, der Übergang wird aufgerufen zweimal. Jede Hilfe wurde dankbar angenommen.

-Code unten, aber hier ist eine Geige https://jsfiddle.net/q8qgbj58/

var n = 243; 
var random = d3.randomNormal(0, .2); 

var duration = 500; 
var now = new Date(Date.now() - duration); 

var svg = d3.select("svg"), 
    margin = {top: 20, right: 20, bottom: 20, left: 40}, 
    width = +svg.attr("width") - margin.left - margin.right, 
    height = +svg.attr("height") - margin.top - margin.bottom, 
    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

var x = d3.scaleTime() 
    .domain([now - (n - 2) * duration, now - duration]) 
    .range([0, width]); 

var y = d3.scaleLinear() 
    .domain([-1, 1]) 
    .range([height, 0]); 

var lineNames = []; 
var lines = {}; 
var data = {}; 

var line = d3.line() 
    .curve(d3.curveBasis) 
    .x(function(d, i) { return x(now - (n - 1 - i) * duration); }) 
    .y(function(d, i) { return y(d); }); 

g.append("defs").append("clipPath") 
    .attr("id", "clip") 
    .append("rect") 
    .attr("width", width) 
    .attr("height", height); 

var axis = g.append("g") 
    .attr("class", "axis axis--x") 
    .attr("transform", "translate(0," + y(0) + ")") 
    .call(d3.axisBottom(x)); 

g.append("g") 
    .attr("class", "axis axis--y") 
    .call(d3.axisLeft(y)); 

createLine("one"); 
createLine("two"); 

d3.selectAll(".line") 
    .transition() 
     .duration(duration) 
     .ease(d3.easeLinear) 
     .on("start", tick); 

function createLine(name) { 
    lineNames.push(name); 

    data[name] = d3.range(n).map(random); 

    lines[name] = d3.line() 
     .curve(d3.curveBasis) 
     .x(function(d, i) { return x(now - (n - 1 - i) * duration); }) 
     .y(function(d, i) { return y(d); }); 

    g.append("g") 
     .attr("clip-path", "url(#clip)") 
     .append("path") 
     .datum(data[name]) 
     .attr("class", "line"); 
} 

function tick() { 
    var index; 
    var i; 
    for (i = 0; i < lineNames.length; ++i) { 
     index = lineNames[i]; 

     // Push a new data point onto the back. 
     data[index].push(random()); 

     // Redraw the line. 
     d3.select(this) 
      .attr("d", lines[index]) 
      .attr("transform", null); 

     // Pop the old data point off the front. 
     data[index].shift(); 
    } 

    now = new Date(); 
    x.domain([now - (n - 2) * duration, now - duration]); 
    axis.transition() 
     .duration(duration) 
     .ease(d3.easeLinear) 
     .call(d3.axisBottom(x)); 


    // Slide it to the left. 
    d3.active(this) 
     .attr("transform", "translate(" + x(now - (n - 1) * duration) + ")") 
    .transition() 
     .on("start", tick); 
} 
+0

Meine anfängliche Neigung ist die Zecke Funktion zweimal aufgerufen wird so oft wie es sollte. Ich könnte mich irren, aber es sieht so aus, als ob die Funktion einmal pro Zeile aufgerufen wird, aber jeder Aufruf wirkt sich auf beide Zeilen aus. Ich hätte erwartet, dass jede Zeile abhebt und nur diese Zeile beeinflusst. Oder ankreuzen, um einmal aufgerufen zu werden und beide Linien zu beeinflussen. –

+0

Ich habe eine Geige hinzugefügt, um das Problem zu zeigen. – SlimCheney

Antwort

2

Es sieht aus wie das Problem mit der Aktualisierung der Daten für alle Zeilen war, als eine Zeile „Tick“ rief. Sie werden bemerken, dass Ihr Beispiel mit 1 Zeile funktioniert und mit 3 Zeilen noch ruckartiger ist. Dies liegt an der for-Schleife im Funktions-Tick. Die Datenbindung in D3 ist sehr nützlich, benötigt aber etwas Zeit, um sich an die Verwendung zu gewöhnen.
Die zwei wichtigsten Codeänderungen, die ich vorgenommen habe, waren, die line() zu einer Variablen zu machen und die for-Schleife von der Tick-Funktion zu entfernen. Eine aktualisierte Geige (Ich habe versucht, nur den ursprünglichen Code Kommentar aus, so können Sie leicht den Unterschied sehen): https://jsfiddle.net/s07d2hs3/

var line = d3.line() 
    .curve(d3.curveBasis) 
    .x(function(d, i) { return x(now - (n - 1 - i) * duration); }) 
    .y(function(d, i) { return y(d); }); 

function tick() { 
    var index; 
    var i; 
    // Push a new data point onto the back. 
    this.__data__.push(random()); 
    // Redraw the line. 
    d3.select(this) 
     .attr("d", line) 
     .attr("transform", null); 

    // Pop the old data point off the front. 
     this.__data__.shift(); 

    now = new Date(); 
    x.domain([now - (n - 2) * duration, now - duration]); 
    axis.transition() 
     .duration(duration) 
     .ease(d3.easeLinear) 
     .call(d3.axisBottom(x)); 

    // Slide it to the left. 
    d3.active(this) 
     .attr("transform", "translate(" + x(now - (n - 1) * duration) + ")") 
    .transition() 
     .on("start", tick); 
} 

Aufgeräumt Geige: https://jsfiddle.net/Lr5dxgr0/2/

+0

Ok, ich denke, ich habe einen Funken Verständnis. Ich glaube, ich verwechselte die Funktion "Linie" mit dem Pfad, der die Linie auf dem Bildschirm darstellt. Deine Geige ist ein wenig verwirrend, aber ich habe mich drum gekümmert. Ich habe meine hier ein bisschen aufgeräumt: https://jsfiddle.net/s07d2hs3/ – SlimCheney

+1

Sorry, für die unordentliche Geige. Ich versuchte zu balancieren, die Antwort zu geben und die Antwort zu zeigen. Es ist sehr hilfreich, einen Breakpoint in Dev-Tools innerhalb der Tick-Funktion zu setzen und dann zu sehen, was "This" enthält. Das Framework wird viele Dinge für Sie im Auge behalten. Ich räumte die Geige auf und fügte den ursprünglichen Beitrag hinzu. –