chart.js ładuje zupełnie nowe dane


89

API dlachart.js umożliwia edycję punktów załadowanych do niego zbiorów danych, na przykład:

.update( )

Wywołanie funkcji update () w Twojej instancji Chart spowoduje ponowne wyrenderowanie wykresu z wszelkimi zaktualizowanymi wartościami, umożliwiając edycję wartości wielu istniejących punktów, a następnie renderowanie ich w jednej animowanej pętli renderowania.

.addData( valuesArray, label )

Wywołanie addData (valuesArray, label) w wystąpieniu Chart, przekazując tablicę wartości dla każdego zestawu danych, wraz z etykietą dla tych punktów.

.removeData( )

Wywołanie funkcji removeData () w Twojej instancji Chart spowoduje usunięcie pierwszej wartości ze wszystkich zestawów danych na wykresie.

Wszystkie są świetne, ale nie mogę dowiedzieć się, jak załadować całkowicie nowy zestaw danych, usuwając stary. Wydaje się, że dokumentacja tego nie obejmuje.

Odpowiedzi:


100

Miałem z tym ogromne problemy

Najpierw spróbowałem, .clear()potem spróbowałem .destroy()i próbowałem ustawić moje odniesienie do wykresu na zero

Co ostatecznie rozwiązało problem: usunięcie <canvas>elementu, a następnie ponowne dołączenie nowego <canvas>do kontenera nadrzędnego


Można to zrobić na milion sposobów:

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);
};

20
Ta odpowiedź działa, ale znalazłem zniszczenie również w najnowszej wersji. Polecane w tym poście - github.com/nnnick/Chart.js/issues/559
HockeyJ

pomogłoby to opróżnieniu elementu div kontenera grafu w usunięciu starych ramek iframe $ ('# wykres wyników'). remove (); $ ('# graph-container'). empty (); $ ('# graph-container'). append ('<canvas id = "results-graph"> <canvas>');
heyyan khan

66

Musisz zniszczyć:

myLineChart.destroy();

Następnie ponownie zainicjuj wykres:

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

2
po prostu użyj tego w ten sposób if (window.myLine) {window.myLine.destroy (); } OR if (myLineChart) {myLineChart.destroy (); }
jayant singh

Potwierdza zniszczenie, a następnie ponowna inicjalizacja nie powoduje migotania i wygląda na to, że punkty danych były aktualizowane dynamicznie
Titan

40

Dzięki Chart.js V2.0 możesz wykonać następujące czynności:

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

18
Dokładnie to, o co prosił op.
Perry

2
Kiedy to robię chart.config.data = newData, pojawia się następujący błąd: TypeError: undefined is not an object (evaluating 'i.data.datasets.length') Ktoś ma ten sam problem?
Benjamin Lucidarme

22

Jest to stary wątek, ale w aktualnej wersji (stan na 1 lutego 2017 r.) Można łatwo zastąpić zestawy danych wykreślone na chart.js:

załóżmy, że nowe wartości na osi x znajdują się w tablicy x, a wartości na osi y w tablicy y, możesz użyć poniższego kodu, aby zaktualizować wykres.

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

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

chart.update();

Wielkie dzięki, stary! Zmarnowany cały dzień. W końcu natknąłem się na twoją odpowiedź. Dziękuję Ci.
Dronacharya

To było pomocne i działało dla mnie. Nawet użycie [] do ustawienia pustego zestawu danych, a następnie wykonanie nowego „wypychania” również załatwi sprawę.
TS

17

ChartJS 2.6 obsługuje zastępowanie odniesień do danych (patrz uwaga w dokumentacji aktualizacji (konfiguracji)). Więc kiedy masz swój wykres, możesz po prostu zrobić to:

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

Nie tworzy animacji, którą można uzyskać po dodaniu punktów, ale istniejące punkty na wykresie zostaną animowane.


12

Moje rozwiązanie jest dość proste. (WERSJA 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 ...

Brak migotania i problemów. getDataSetto funkcja kontrolująca, jaki zestaw danych muszę przedstawić


Czy możesz również dodać fragment kodu funkcji getDataSet ()?
Gotham's Reckoning

1
Dodano przykład getDataSet ()
Henrique C.


6

Według dokumentów, clear()czyści płótno. Potraktuj to jako narzędzie Gumka w programie Paint. Nie ma to nic wspólnego z danymi aktualnie załadowanymi w instancji wykresu.

Niszczenie instancji i tworzenie nowej jest marnotrawstwem. Zamiast tego użyj metod API removeData()i addData(). Spowoduje to dodanie / usunięcie pojedynczego segmentu do / z instancji wykresu. Więc jeśli chcesz załadować zupełnie nowe dane, po prostu zapętl tablicę danych wykresu i wywołaj removeData(index)(indeksy tablic powinny odpowiadać indeksom bieżącego segmentu). Następnie użyj, addData(index)aby wypełnić go nowymi danymi. Sugeruję zawijanie dwóch metod zapętlania danych, ponieważ oczekują one indeksu pojedynczego segmentu. Używam resetCharti updateChart. Zanim przejdziesz dalej, sprawdź Chart.jsnajnowszą wersję i dokumentację. Być może dodali nowe metody całkowitego zastąpienia danych .


3
Podoba mi się twoja odpowiedź i jest ona zgodna z informacjami, które czytałem w sieci. Jeśli jesteś w stanie pokazać i dać przykład, byłoby to naprawdę pomocne. Dwa podobne przykłady, które widziałem w Internecie, to: jsbin.com/yitep/5/edit?html,js,output i jsbin.com/yitep/4/edit?html,js,output
Rethabile

Jedynym problemem jest to, że aktualizacja wykresu staje się niezwykle uciążliwa i bardzo powolna, jeśli musisz zastąpić dane wykresu zasadniczo zupełnie innym zestawem danych. Na początek, nie znaleźli sposób, aby zaktualizować istniejące oś x etykiety . Zniszczenie i przywrócenie całego wykresu jest jedynym realnym rozwiązaniem w takich okolicznościach.
deceze

Niestety, miałem do czynienia tylko z wykresem pierścieniowym, który jest mniej złożony. Czy sprawdziłeś najnowsze API?
adi518

4

Natknąłem się na ten sam problem, na stronie mam 6 wykresów kołowych, które można aktualizować w tym samym czasie. Używam następującej funkcji, aby zresetować dane wykresu.

// 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();


Chociaż to działa, odkryłem, że jest znacznie wolniejsze (ze względu na animację podczas dodawania każdego punktu) w porównaniu z całkowitym odtworzeniem wykresu.
Danila Vershinin

3

Próbowałem rozwiązania neaumusic , ale później odkryłem, że jedynym problemem z niszczeniem jest luneta .

var chart;

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

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

Przeniesienie zmiennej wykresu poza zakres funkcji sprawiło, że zadziałało.


3

Żadna z powyższych odpowiedzi nie pomogła mojej konkretnej sytuacji w bardzo czysty sposób przy minimalnym kodzie. Musiałem usunąć wszystkie zestawy danych, a następnie zapętlić, aby dynamicznie dodać kilka zestawów danych. Więc to wycięte jest dla tych, którzy docierają na sam dół strony bez znalezienia odpowiedzi :)

Uwaga: pamiętaj, aby wywołać funkcję chart.update () po załadowaniu wszystkich nowych danych do obiektu zestawu danych. Mam nadzieję, że to komuś pomoże

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

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

2

Musisz wyczyścić stare dane. Nie ma potrzeby ponownej inicjalizacji:

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

1

Jeśli ktoś szuka, jak to zrobić w React. W przypadku wykresu linii, zakładając, że wokół wykresu znajduje się element opakowujący:

(Zakładamy, że używasz v2. Nie musisz tego używać react-chartjs. To jest używany normalny chart.jspakiet z 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>
  );
}

componentDidUpdateFunkcjonalność pozwala na aktualizację, dodać lub usunąć dane z this.props.data.


1

Nie jest konieczne niszczenie wykresu. Spróbuj z tym

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

Dowiedz się, jak działa Chart.js (wersja 2 tutaj) i zrób to dla dowolnego atrybutu:


1. Przypuśćmy, że w kodzie HTML znajduje się wykres słupkowy taki jak poniżej:

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

2. Załóżmy, że masz kod javascript, który wypełnia wykres po raz pierwszy (na przykład po załadowaniu strony):

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}
    }
});

Załóżmy, że chcesz w pełni zaktualizować swój zestaw danych. To bardzo proste. Spójrz na powyższy kod i zobacz, jaka jest ścieżka od zmiennej wykresu do danych, a następnie postępuj zgodnie z poniższą ścieżką:

  • Wybierz chartInstance var.
  • Następnie wybierz data nodewewnątrzchartInstance .
  • Następnie wybierz datasets nodewewnątrz data node.
    (uwaga: jak widać, datasets nodejest to tablica, więc musisz określić, który element tej tablicy chcesz. tutaj mamy tylko jeden element w datasets node., więc używamydatasets[0]
  • Więc wybierz datasets[0]
  • Następnie wybierz data nodewnętrze w datasets[0].


Ta czynność pozwala chartInstance.data.datasets[0].dataustawić nowe dane i zaktualizować wykres:

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


Uwaga: postępując zgodnie z powyższym algorytmem, możesz po prostu dotrzeć do każdego węzła, który chcesz .


0

Jedynym rozwiązaniem, które do tej pory mogę znaleźć dla siebie, jest ponowna inicjalizacja wykresu od zera:

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

Jednak wydaje mi się to trochę dziwne. Czy jest ktoś lepsze, bardziej standardowe rozwiązanie?


1
To prawie działa dla mnie, z wyjątkiem tego, że musisz najpierw wykonać myLineChart.destroy (), aby pozbyć się starego, albo będziesz mieć migotanie podczas przerysowywania.
user3413723

0

Ja też miałem z tym mnóstwo problemów. Mam dane i etykiety w oddzielnych tablicach, a następnie ponownie inicjuję dane wykresu. Dodałem line.destroy (); jak zasugerowano powyżej, który załatwił sprawę

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


0

Nie jest zrobić bez czyszczenia kanwy lub rozpoczynania od nowa, ale musisz samodzielnie zająć się tworzeniem wykresu, aby dane były w tym samym formacie podczas aktualizacji.

Oto jak to zrobiłem.

    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;
        }

Zasadniczo wyrzucam dane załadowane podczas tworzenia, a następnie przekształcam za pomocą metody dodawania danych. Oznacza to, że mam wtedy dostęp do wszystkich punktów. Ilekroć próbowałem uzyskać dostęp do struktury danych utworzonej przez:

Chart(ctx).Bar(dataNew);

polecenie, nie mam dostępu do tego, czego potrzebuję. Oznacza to, że możesz zmienić wszystkie punkty danych w ten sam sposób, w jaki je utworzyłeś, a także wywołać funkcję update () bez animacji całkowicie od zera.


0

Wykres JS 2.0

Po prostu ustaw chart.data.labels = [];

Na przykład:

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();

0

Podczas tworzenia obiektu wykresu musisz zapisać instancję w zmiennej.

var currentChart = new Chart(ctx, ...);

A przed załadowaniem nowych danych musisz je zniszczyć :

currentChart.destroy();
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.