2016-06-07 9 views
2

Ich bin ziemlich neu in D3 und habe versucht, alles herauszufinden. Ich versuche dieses Beispiel here zu konfigurieren, um mit neuen Daten zu aktualisieren und entsprechend zu wechseln. HierWie können Daten sauber entfernt werden, bevor d3.js chart aktualisiert wird?

ist der Code Stift I konfiguriert habe (klicken Sie auf das Absenden zu aktualisieren) http://codepen.io/anon/pen/pbjLRW?editors=1010

Von dem, was ich sammeln kann, indem ein gewisse Variation von .exit() ist für einen sauberen Datenübergang erforderlich, aber nach dem Lesen einige Tutorials Ich finde es immer noch schwierig zu wissen, wie es funktioniert. Ich habe Beispiele gesehen, bei denen das Entfernen der Container vor dem Aufrufen der Zeichenfunktion funktioniert, aber aufgrund meiner begrenzten Erfahrung kann es beim Datenwechsel zu einem Flimmern kommen, so dass ich nicht sicher bin, ob es die beste Vorgehensweise ist.

Jetzt bin ich nicht sicher, warum die Daten in meinem Codepen nicht korrekt aktualisiert werden, aber mein Hauptanliegen ist, den Übergang richtig zu machen. Idealerweise würde ich gerne wissen, wie ich die Nadel beim Datenwechsel einfach bewegen könnte, also würde es beispielsweise von 90> 40 anstelle von 90> 0> 40 gehen.

Allerdings werde ich mich definitiv damit begnügen herauszufinden warum Es wird nicht am selben Ort neu gezeichnet, wenn Sie im verknüpften CodePen auf "Senden" klicken.

Hier ist meine Update-Funktion;

function updateGuage() { 
    d3.selectAll("text").remove() 
    d3.selectAll('.needle').remove() 
    chart.remove() 
    name = "qwerty"; 
    value = "25"; 
    drawGuage(); 
} 

initial zeichnen;

function drawGuage() { 
    percToDeg = function(perc) { 
    return perc * 360; 
    }; 

    percToRad = function(perc) { 
    return degToRad(percToDeg(perc)); 
    }; 

    degToRad = function(deg) { 
    return deg * Math.PI/180; 
    }; 

    // Create SVG element 
    svg = el.append('svg').attr('width', width + margin.left + margin.right).attr('height', height + margin.top + margin.bottom); 

    // Add layer for the panel 
    chart = svg.append('g').attr('transform', "translate(" + ((width + margin.left)/2) + ", " + ((height + margin.top)/2) + ")"); 

    chart.append('path').attr('class', "arc chart-first"); 
    chart.append('path').attr('class', "arc chart-second"); 
    chart.append('path').attr('class', "arc chart-third"); 

    arc3 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth) 
    arc2 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth) 
    arc1 = d3.svg.arc().outerRadius(radius - chartInset).innerRadius(radius - chartInset - barWidth) 

    repaintGauge = function() { 
     perc = 0.5; 
     var next_start = totalPercent; 
     arcStartRad = percToRad(next_start); 
     arcEndRad = arcStartRad + percToRad(perc/3); 
     next_start += perc/3; 

     arc1.startAngle(arcStartRad).endAngle(arcEndRad); 

     arcStartRad = percToRad(next_start); 
     arcEndRad = arcStartRad + percToRad(perc/3); 
     next_start += perc/3; 

     arc2.startAngle(arcStartRad + padRad).endAngle(arcEndRad); 

     arcStartRad = percToRad(next_start); 
     arcEndRad = arcStartRad + percToRad(perc/3); 

     arc3.startAngle(arcStartRad + padRad).endAngle(arcEndRad); 

     chart.select(".chart-first").attr('d', arc1); 
     chart.select(".chart-second").attr('d', arc2); 
     chart.select(".chart-third").attr('d', arc3); 

    } 
    ///////// 

    var texts = svg.selectAll("text") 
    .data(dataset) 
    .enter(); 

    texts.append("text") 
    .text(function() { 
     return dataset[0].metric; 
    }) 
    .attr('id', "Name") 
    .attr('transform', "translate(" + ((width + margin.left)/6) + ", " + ((height + margin.top)/1.5) + ")") 
    .attr("font-size", 25) 
    .style("fill", "#000000"); 

    var trX = 180 - 210 * Math.cos(percToRad(percent/2)); 
    var trY = 195 - 210 * Math.sin(percToRad(percent/2)); 
    // (180, 195) are the coordinates of the center of the gauge. 

    displayValue = function() { 
    texts.append("text") 
     .text(function() { 
     return dataset[0].value; 
     }) 
     .attr('id', "Value") 
     .attr('transform', "translate(" + trX + ", " + trY + ")") 
     .attr("font-size", 18) 
     .style("fill", '#000000'); 
    } 

    texts.append("text") 
    .text(function() { 
     return 0; 
    }) 
    .attr('id', 'scale0') 
    .attr('transform', "translate(" + ((width + margin.left)/100) + ", " + ((height + margin.top)/2) + ")") 
    .attr("font-size", 15) 
    .style("fill", "#000000"); 

    texts.append("text") 
    .text(function() { 
     return gaugeMaxValue/2; 
    }) 
    .attr('id', 'scale10') 
    .attr('transform', "translate(" + ((width + margin.left)/2.15) + ", " + ((height + margin.top)/30) + ")") 
    .attr("font-size", 15) 
    .style("fill", "#000000"); 

    texts.append("text") 
    .text(function() { 
     return gaugeMaxValue; 
    }) 
    .attr('id', 'scale20') 
    .attr('transform', "translate(" + ((width + margin.left)/1.03) + ", " + ((height + margin.top)/2) + ")") 
    .attr("font-size", 15) 
    .style("fill", "#000000"); 

    var Needle = (function() { 

    //Helper function that returns the `d` value for moving the needle 
    var recalcPointerPos = function(perc) { 
     var centerX, centerY, leftX, leftY, rightX, rightY, thetaRad, topX, topY; 
     thetaRad = percToRad(perc/2); 
     centerX = 0; 
     centerY = 0; 
     topX = centerX - this.len * Math.cos(thetaRad); 
     topY = centerY - this.len * Math.sin(thetaRad); 
     leftX = centerX - this.radius * Math.cos(thetaRad - Math.PI/2); 
     leftY = centerY - this.radius * Math.sin(thetaRad - Math.PI/2); 
     rightX = centerX - this.radius * Math.cos(thetaRad + Math.PI/2); 
     rightY = centerY - this.radius * Math.sin(thetaRad + Math.PI/2); 

     return "M " + leftX + " " + leftY + " L " + topX + " " + topY + " L " + rightX + " " + rightY; 

    }; 

    function Needle(el) { 
     this.el = el; 
     this.len = width/2.5; 
     this.radius = this.len/8; 
    } 

    Needle.prototype.render = function() { 
     this.el.append('circle').attr('class', 'needle-center').attr('cx', 0).attr('cy', 0).attr('r', this.radius); 

     return this.el.append('path').attr('class', 'needle').attr('id', 'client-needle').attr('d', recalcPointerPos.call(this, 0)); 

    }; 

    Needle.prototype.moveTo = function(perc) { 
     var self, 
     oldValue = this.perc || 0; 

     this.perc = perc; 
     self = this; 

     // Reset pointer position 
     this.el.transition().delay(100).ease('quad').duration(200).select('.needle').tween('reset-progress', function() { 
     return function(percentOfPercent) { 
      var progress = (1 - percentOfPercent) * oldValue; 

      repaintGauge(progress); 
      return d3.select(this).attr('d', recalcPointerPos.call(self, progress)); 
     }; 
     }); 

     this.el.transition().delay(300).ease('bounce').duration(1500).select('.needle').tween('progress', function() { 
     return function(percentOfPercent) { 
      var progress = percentOfPercent * perc; 

      repaintGauge(progress); 
      return d3.select(this).attr('d', recalcPointerPos.call(self, progress)); 
     }; 
     }); 

    }; 

    return Needle; 

    })(); 

    needle = new Needle(chart); 
    needle.render(); 
    needle.moveTo(percent); 

    setTimeout(displayValue, 1350); 

} 

Jede Hilfe/Beratung sehr geschätzt wird,

Dank

Antwort

0

Es ist wichtig zu wissen, dass es drei verschiedene Operationen, die Sie nach der Bindung Daten durchführen können. Behandle Ergänzungen, Löschungen und modifiziere Dinge, die sich nicht geändert haben (oder gerade hinzugefügt wurden).

Hier ist ein Beispiel das Erstellen und eine einfache Liste Manipulation: http://jsbin.com/sekuhamico/edit?html,css,js,output

var update =() => { 

    // bind data to list elements 
    // think of listWithData as a virtual representation of 
    // the array of list items you will later see in the 
    // DOM. d3.js does not handle the mapping from this 
    // virtual structure to the DOM for you. It is your task 
    // to define what is to happen with elements that are 
    // added, removed or updated. 
    var listWithData = ul.selectAll('li').data(listItems); 

    // handle additions 
    // by calling enter() on our virtual list, you get the 
    // subset of entries which need to be added to the DOM 
    // as their are not yet present there. 
    listWithData.enter().append('li').text(i => i.text).on('click', i => toggle(i)); 

    // handle removal 
    // by calling exit() on our virtual list, you get the 
    // subset of entries which need to be removed from the 
    // DOM as they are not longer present in the virtual list. 
    listWithData.exit().remove(); 

    // update existing 
    // acting directly on the virtual list will update any 
    // elements currently present in the DOM. If you would 
    // execute this line before calling exit(), you would 
    // also manipulate those items to be removed. If you 
    // would even call it before calling enter() you would 
    // miss on updating the newly added element. 
    listWithData.attr('class', i => i.active ? 'active' : ''); 

}; 

Beachten Sie, dass Sie wahrscheinlich in Wirklichkeit brauchen eine Art von ID zu Ihrem Artikel hinzufügen. Um sicherzustellen, dass die richtigen Artikel entfernt werden und keine Probleme mit der Bestellung auftreten.

Erklärung

Die Update-Funktion weiß nichts über das, was, oder auch wenn sich etwas geändert hat. Es ist nicht bekannt, ob neue Datenelemente vorhanden sind oder alte entfernt wurden. Aber beides könnte passieren. Daher behandeln wir beide Fälle durch Aufruf von bzw. exit(). Die d3-Funktionen und exit() liefern uns die Teilmengen von Listenelementen, die hinzugefügt oder entfernt werden sollen. Schließlich müssen wir uns um Änderungen in den vorhandenen Daten kümmern.

+0

Ich verstehe nicht, wie/warum Sie aufrufen. Exit(). Remove(); in der gleichen Funktion wie für die Eingabe der Daten? – since095

1

Was Sie auschecken möchten, ist How selections work geschrieben von Mike Bostock. Nach dem Lesen dieses Artikels, alles um eingeben, Update und Ausfahrt Auswahlen werden klarer.

Auf den Punkt gebracht:

  1. Sie mit selectAll('li')
  2. eine Auswahl von Elementen erstellen Sie die Auswahl mit einem Daten Array durch Aufruf data([...])
  3. Nun vergleicht D3, was bereits beitreten im DOM mit den verbundenen Daten. Jedes DOM-Element, das auf diese Weise verarbeitet wird, hat eine __data__-Eigenschaft, die D3 zu ein Datenelement an ein Element binden lässt.
  4. Nachdem Sie Daten hinzugefügt haben, erhalten Sie die Eingabe durch den Aufruf enter(). Dies ist jedes Datenelement, das noch nicht an die ausgewählten DOM-Elemente gebunden wurde. Normalerweise verwenden Sie die Eingabeauswahl, um neue Elemente zu erstellen, z. durch append()
  5. Durch den Aufruf exit() erhalten Sie die Ausfahrt Auswahl. Dies sind alle bereits vorhandenen DOM-Elemente, denen nach dem Join kein Datenelement mehr zugeordnet ist. Normalerweise verwenden Sie die Exit-Auswahl, um DOM-Elemente mit remove()
  6. zu entfernen. Die so genannte Update-Auswahl ist die eine Sache, die nach dem Beitritt der Auswahl mit data() zurückgegeben wurde. Sie möchten die Update-Auswahl in einer Variablen speichern, damit Sie auch nach dem Aufruf von oder exit() darauf zugreifen können. Hinweis: Wenn Sie bereits Elemente über die Eingabeauswahl hinzugefügt haben, enthält die Aktualisierungsauswahl auch diese neu erstellten DOM-Elemente. Es ist wichtig zu wissen, dass sich die Update-Auswahl ändert, nachdem Sie neue Elemente erstellt haben.
+1

Punkt (6) war der Kern dessen, was mich an D3 immer etwas verwirrt hat. Können Sie bestätigen, dass sich dies in D3 Version 4 nicht geändert hat? Dieser Kommentar schlägt vor, es hat: https://github.com/d3/d3-selection/issues/86#issuecomment-291446865 –

+0

In der Tat, es hat sich geändert. Siehe [d3/CHANGES.md unter master · d3/d3] (https://github.com/d3/d3/blob/master/CHANGES.md#selections-d3-selection) * "Zusätzlich Auswahl. append führt die Eingabe von Knoten nicht mehr in die Update-Auswahl ein. Verwenden Sie selection.merge, um die Eingabe zu kombinieren und nach einem Daten-Join zu aktualisieren. "* – rmoestl

Verwandte Themen