chart.js lädt völlig neue Daten


85

Mit der API fürchart.js können Punkte der darin geladenen Datensätze bearbeitet werden, z. B.:

.update( )

Wenn Sie update () in Ihrer Diagramminstanz aufrufen, wird das Diagramm mit allen aktualisierten Werten erneut gerendert, sodass Sie den Wert mehrerer vorhandener Punkte bearbeiten und diese dann in einer animierten Renderschleife rendern können.

.addData( valuesArray, label )

Rufen Sie addData (valuesArray, label) in Ihrer Chart-Instanz auf und übergeben Sie ein Array von Werten für jedes Dataset sowie eine Beschriftung für diese Punkte.

.removeData( )

Durch Aufrufen von removeData () in Ihrer Diagramminstanz wird der erste Wert für alle Datensätze im Diagramm entfernt.

All dies ist großartig, aber ich kann nicht herausfinden, wie ein völlig neuer Datensatz geladen und der alte gelöscht wird. Die Dokumentation scheint dies nicht abzudecken.

Antworten:


98

Ich hatte große Probleme damit

Zuerst habe ich es versucht, .clear()dann habe ich es versucht .destroy()und ich habe versucht, meine Diagrammreferenz auf null zu setzen

Was das Problem für mich endgültig behoben hat: Löschen des <canvas>Elements und erneutes Anhängen eines neuen Elements <canvas>an den übergeordneten Container


Es gibt eine Million Möglichkeiten, dies zu tun:

var resetCanvas = function () {
  $('#results-graph').remove(); // this is my <canvas> element
  $('#graph-container').append('<canvas id="results-graph"><canvas>');
  canvas = document.querySelector('#results-graph'); // why use jQuery?
  ctx = canvas.getContext('2d');
  ctx.canvas.width = $('#graph').width(); // resize to parent width
  ctx.canvas.height = $('#graph').height(); // resize to parent height

  var x = canvas.width/2;
  var y = canvas.height/2;
  ctx.font = '10pt Verdana';
  ctx.textAlign = 'center';
  ctx.fillText('This text is centered on the canvas', x, y);
};

18
Diese Antwort funktioniert, aber ich habe festgestellt, dass destroy auch in der neuesten Version funktioniert. Empfohlen auf diesem Beitrag - github.com/nnnick/Chart.js/issues/559
HockeyJ

es würde dem leeren Graph-Container-Div helfen, alte iframes $ ('# results-graph') zu entfernen. remove (); $ ('# graph-container'). empty (); $ ('# graph-container'). append ('<canvas id = "results-graph"> <canvas>');
Heyyan Khan

64

Sie müssen zerstören:

myLineChart.destroy();

Initialisieren Sie dann das Diagramm neu:

var ctx = document.getElementById("myChartLine").getContext("2d");
myLineChart = new Chart(ctx).Line(data, options);

2
benutze es einfach so if (window.myLine) {window.myLine.destroy (); } ODER if (myLineChart) {myLineChart.destroy (); }
Jayant Singh

Kann bestätigen, dass das Zerstören und erneute Initialisieren kein Flackern verursacht und anscheinend die Datenpunkte dynamisch aktualisiert wurden
Titan

39

Mit Chart.js V2.0 können Sie Folgendes tun:

websiteChart.config.data = some_new_data;
websiteChart.update();

17
Genau das, wonach die Operation gefragt hat.
Perry

2
Wenn ich das tue chart.config.data = newData, habe ich diesen Fehler: TypeError: undefined is not an object (evaluating 'i.data.datasets.length') Jemand hat das gleiche Problem?
Benjamin Lucidarme

21

Es ist ein alter Thread, aber in der aktuellen Version (Stand: 1. Februar 2017) ist es einfach, auf chart.js dargestellte Datensätze zu ersetzen:

Angenommen, Ihre neuen x-Achsenwerte befinden sich im Array x und die y-Achsenwerte im Array y. Sie können den folgenden Code verwenden, um das Diagramm zu aktualisieren.

var x = [1,2,3];
var y = [1,1,1];

chart.data.datasets[0].data = y;
chart.data.labels = x;

chart.update();

Vielen Dank, Mann! Den ganzen Tag verschwendet. Schließlich stolperte über Ihre Antwort. Danke dir.
Dronacharya

Das war hilfreich und hat bei mir funktioniert. Selbst wenn Sie nur [] verwenden, um einen leeren Datensatz festzulegen, und dann einen neuen "Push" ausführen, reicht dies ebenfalls aus.
TS

17

ChartJS 2.6 unterstützt das Ersetzen von Datenreferenzen (siehe Hinweis in der Dokumentation zur Aktualisierung (Konfiguration)). Wenn Sie also Ihr Diagramm haben, können Sie dies einfach tun:

myChart.data.labels = ['1am', '2am', '3am', '4am'];
myChart.data.datasets[0].data = [0, 12, 35, 36];
myChart.update();

Die Animation, die Sie durch das Hinzufügen von Punkten erhalten, wird nicht ausgeführt, aber vorhandene Punkte im Diagramm werden animiert.


12

Meine Lösung dafür ist ziemlich einfach. (VERSION 1.X)

getDataSet:function(valuesArr1,valuesArr2){
        var dataset = [];
        var arr1 = {
            label: " (myvalues1)",
            fillColor: "rgba(0, 138, 212,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(0, 138, 212,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: valuesArr1
        };
        var arr2 = {
            label: " (myvalues2)",
            fillColor: "rgba(255, 174, 087,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(255, 174, 087,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: valuesArr2
        };
        /*Example conditions*/
        if(condition 1)
          dataset.push(arr1);
        }
        if(condition 2){
          dataset.push(arr1);
          dataset.push(arr2);
        }

        return dataset;
    }

var data = {
    labels: mylabelone,
    datasets: getDataSet()
};
if(myBarChart != null) // i initialize myBarChart var with null
    myBarChart.destroy(); // if not null call destroy
    myBarChart = new Chart(ctxmini).Bar(data, options);//render it again ...

Kein Flackern oder Probleme. getDataSetist eine Funktion, um zu steuern, welchen Datensatz ich präsentieren muss


Können Sie auch das Code-Snippet von getDataSet () hinzufügen?
Gotham

1
Das Beispiel getDataSet () wurde hinzugefügt
Henrique C.


6

Löscht laut docs clear()die Leinwand. Betrachten Sie es als das Radiergummi-Werkzeug in Paint. Es hat nichts mit den aktuell in die Diagramminstanz geladenen Daten zu tun.

Das Zerstören der Instanz und das Erstellen einer neuen Instanz ist verschwenderisch. Verwenden Sie stattdessen API-Methoden removeData()und addData(). Diese fügen der Diagramminstanz ein einzelnes Segment hinzu bzw. entfernen es. Wenn Sie also vollständig neue Daten laden möchten, schleifen Sie einfach ein Diagrammdatenarray und rufen Sie auf removeData(index)(Array-Indizes sollten den aktuellen Segmentindizes entsprechen). Verwenden Sie dann addData(index), um es mit den neuen Daten zu füllen. Ich schlage vor, die beiden Methoden zum Schleifen der Daten zu verpacken, da sie einen einzelnen Segmentindex erwarten. Ich benutze resetChartund updateChart. Bevor Sie fortfahren, stellen Sie sicher, dass Sie die Chart.jsneueste Version und Dokumentation überprüfen . Möglicherweise haben sie neue Methoden zum vollständigen Ersetzen der Daten hinzugefügt .


3
Ich mag Ihre Antwort und sie stimmt mit den Informationen überein, die ich online gelesen habe. Wenn Sie in der Lage sind, ein Beispiel zu zeigen, wäre das wirklich hilfreich. Die zwei Beispiele, die ich online gesehen habe und die ähnlich sind, sind: jsbin.com/yitep/5/edit?html,js,output und jsbin.com/yitep/4/edit?html,js,output
Rethabile

Das einzige Problem besteht darin, dass das Aktualisieren eines Diagramms extrem umständlich und sehr langsam wird, wenn Sie die Diagrammdaten durch ein wesentlich anderes Dataset ersetzen müssen. Für den Anfang habe ich keine Möglichkeit gefunden, vorhandene x-Achsen- Beschriftungen zu aktualisieren . Unter solchen Umständen ist die Zerstörung und Wiederherstellung des gesamten Diagramms die einzig wahre Lösung.
Täuschung

Leider habe ich mich nur mit einem Donut-Diagramm befasst, das weniger komplex ist. Haben Sie die neueste API überprüft?
adi518

4

Ich bin auf dasselbe Problem gestoßen. Ich habe 6 Kreisdiagramme auf einer Seite, die alle gleichzeitig aktualisiert werden können. Ich verwende die folgende Funktion, um Diagrammdaten zurückzusetzen.

// sets chart segment data for previously rendered charts
function _resetChartData(chart, new_segments) {
    // remove all the segments
    while (chart.segments.length) {
        chart.removeData();
    };

    // add the new data fresh
    new_segments.forEach (function (segment, index) {
        chart.addData(segment, index);
    });
};

// when I want to reset my data I call
_resetChartData(some_chart, new_data_segments);
some_chart.update();


Während dies funktioniert, stellte ich fest, dass es viel langsamer ist (aufgrund von Animationen beim Hinzufügen jedes Punkts) als das gesamte Diagramm neu zu erstellen.
Danila Vershinin

3

Ich habe versucht, eine neaumusische Lösung zu finden, aber später herausgefunden, dass das einzige Problem bei der Zerstörung der Umfang ist .

var chart;

function renderGraph() {
    // Destroy old graph
    if (chart) {
        chart.destroy();
    }

    // Render chart
    chart = new Chart(
        document.getElementById(idChartMainWrapperCanvas),
        chartOptions
    );
}

Wenn ich meine Diagrammvariable außerhalb des Funktionsumfangs verschiebe, funktioniert sie für mich.


3

Keine der oben genannten Antworten hat meiner speziellen Situation auf sehr saubere Weise mit minimalem Code geholfen. Ich musste alle Datensätze entfernen und dann eine Schleife ausführen, um mehrere Datensätze dynamisch hinzuzufügen. Dieser Ausschnitt ist also für diejenigen gedacht, die es bis zum Ende der Seite schaffen, ohne ihre Antwort zu finden :)

Hinweis: Stellen Sie sicher, dass Sie chart.update () aufrufen, sobald Sie alle neuen Daten in das Dataset-Objekt geladen haben. Hoffe das hilft jemandem

function removeData(chart) {
   chart.data.datasets.length = 0;
}

function addData(chart, data) {
  chart.data.datasets.push(data);
}

2

Sie müssen alte Daten bereinigen. Keine erneute Initialisierung erforderlich:

for (i in myChartLine.datasets[0].points)
    myChartLine.removeData();

1

Wenn jemand nach einer Möglichkeit sucht, dies in React zu tun. Angenommen, Sie haben eine Wrapper-Komponente um das Diagramm:

(Dies setzt voraus, dass Sie v2 verwenden. Sie müssen es nicht verwenden react-chartjs. Dies verwendet das normale chart.jsPaket von npm.)

propTypes: {
  data: React.PropTypes.shape({
    datasets: React.PropTypes.arrayOf(
      React.PropTypes.shape({

      })
    ),
    labels: React.PropTypes.array.isRequired
  }).isRequired
},
componentDidMount () {
  let chartCanvas = this.refs.chart;

  let myChart = new Chart(chartCanvas, {
    type: 'line',
    data: this.props.data,
    options: {
      ...
    }
  });

  this.setState({chart: myChart});
},
componentDidUpdate () {
    let chart = this.state.chart;
    let data = this.props.data;

    data.datasets.forEach((dataset, i) => chart.data.datasets[i].data = dataset.data);

    chart.data.labels = data.labels;
    chart.update();
},
render () {
  return (
    <canvas ref={'chart'} height={'400'} width={'600'}></canvas>
  );
}

Mit dieser componentDidUpdateFunktion können Sie Daten aktualisieren, hinzufügen oder entfernen this.props.data.


1

Es ist nicht notwendig, das Diagramm zu zerstören. Versuchen Sie es damit

function removeData(chart) {

        let total = chart.data.labels.length;

        while (total >= 0) {
            chart.data.labels.pop();
            chart.data.datasets[0].data.pop();
            total--;
        }

        chart.update();
    }

1

Bitte erfahren Sie, wie Chart.js (Version 2 hier) funktioniert, und tun Sie dies für jedes gewünschte Attribut:


1.Bitte nehmen Sie an, Sie haben ein Balkendiagramm wie das folgende in Ihrem HTML:

<canvas id="your-chart-id" height="your-height" width="your-width"></canvas>

2.Bitte nehmen Sie an, Sie haben einen Javascript-Code, der Ihr Diagramm zum ersten Mal ausfüllt (z. B. wenn eine Seite geladen wird):

var ctx = document.getElementById('your-chart-id').getContext('2d');
var chartInstance = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: your-lables-array,
        datasets: [{
            data: your-data-array,
            /*you can create random colors dynamically by ColorHash library [https://github.com/zenozeng/color-hash]*/
            backgroundColor: your-lables-array.map(function (item) {
                return colorHash.hex(item);
            })
        }]
    },
    options: {
        maintainAspectRatio: false,
        scales: {
            yAxes: [ { ticks: {beginAtZero: true} } ]
        },
        title: {display: true, fontSize: 16, text: 'chart title'},
        legend: {display: false}
    }
});

Angenommen, Sie möchten Ihren Datensatz vollständig aktualisieren. Es ist sehr einfach. Sehen Sie sich den obigen Code an und sehen Sie, wie der Pfad von Ihrer Diagrammvariablen zu den Daten ist. Folgen Sie dann dem folgenden Pfad:

  • Wählen Sie chartInstancevar.
  • Wählen Sie dann data nodeinnerhalb der chartInstance.
  • Wählen Sie dann datasets nodeinnerhalb der data node.
    (Hinweis: Wie Sie sehen können, datasets nodeist das ein Array. Sie müssen also angeben, welches Element dieses Arrays Sie möchten. Hier haben wir nur ein Element in der datasets node., also verwenden wirdatasets[0]
  • Also wählen Sie datasets[0]
  • Dann wählen Sie data nodeinnen in der datasets[0].


Mit diesen Schritten chartInstance.data.datasets[0].datakönnen Sie neue Daten festlegen und das Diagramm aktualisieren:

chartInstance.data.datasets[0].data = NEW-your-data-array
//finally update chart var:
chartInstance.update();


Hinweis: Wenn Sie dem obigen Algorithmus folgen, können Sie einfach jeden gewünschten Knoten erreichen .


0

Die einzige Lösung, die ich bisher für mich finden kann, besteht darin, das Diagramm von Grund auf neu zu initialisieren:

var myLineChart = new Chart(ctx).Line(data, options);

Dies scheint mir jedoch ein bisschen hokey. Gibt es eine bessere, standardisiertere Lösung?


1
Dies funktioniert so ziemlich für mich, außer dass Sie zuerst myLineChart.destroy () ausführen müssen, um das alte zu entfernen, oder Sie werden ein Flimmern haben, wenn es neu gezeichnet wird.
user3413723

0

Ich hatte auch viele Probleme damit. Ich habe Daten und Beschriftungen in separaten Arrays, dann initialisiere ich die Diagrammdaten neu. Ich habe die line.destroy () hinzugefügt; wie oben vorgeschlagen, was den Trick getan hat

var ctx = document.getElementById("canvas").getContext("2d");
if(window.myLine){
	window.myLine.destroy();
}
window.myLine = new Chart(ctx).Line(lineChartData, {
  etc
  etc


0

Es gibt eine Möglichkeit, dies zu tun, ohne die Zeichenfläche zu löschen oder von vorne zu beginnen. Sie müssen jedoch die Erstellung des Diagramms so handhaben, dass die Daten beim Aktualisieren dasselbe Format haben.

Hier ist, wie ich es gemacht habe.

    var ctx = document.getElementById("myChart").getContext("2d");
    if (chartExists) {
        for (i=0;i<10;i++){
            myNewChart.scale.xLabels[i]=dbLabels[i]; 
            myNewChart.datasets[0].bars[i].value=dbOnAir[i];
        }
        myNewChart.update();
      }else{
          console.log('chart doesnt exist');
          myNewChart = new Chart(ctx).Bar(dataNew);
          myNewChart.removeData();
          for (i=0;i<10;i++){
              myNewChart.addData([10],dbLabels[i]);
          }
          for (i=0;i<10;i++){      
              myNewChart.datasets[0].bars[i].value=dbOnAir[i];
          }
          myNewChart.update();
          chartExists=true;
        }

Grundsätzlich verschrotte ich die bei der Erstellung geladenen Daten und reformiere sie dann mit der Methode zum Hinzufügen von Daten. Dies bedeutet, dass ich dann auf alle Punkte zugreifen kann. Wann immer ich versucht habe, auf die Datenstruktur zuzugreifen, die erstellt wird von:

Chart(ctx).Bar(dataNew);

Befehl, ich kann nicht auf das zugreifen, was ich brauche. Dies bedeutet, dass Sie alle Datenpunkte auf die gleiche Weise ändern können, wie Sie sie erstellt haben, und auch update () aufrufen können, ohne sie vollständig von Grund auf neu zu animieren.


0

Diagramm JS 2.0

Setzen Sie einfach chart.data.labels = [];

Beispielsweise:

function addData(chart, label, data) {
    chart.data.labels.push(label);
    chart.data.datasets.forEach((dataset) => {
       dataset.data.push(data);
    });
    chart.update();
}

$chart.data.labels = [];

$.each(res.grouped, function(i,o) {
   addData($chart, o.age, o.count);
});
$chart.update();
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.