chart.js carrega dados totalmente novos

87

A API parachart.js permite editar pontos dos conjuntos de dados carregados nele, por exemplo:

.update( )

Chamar update () em sua instância de gráfico irá renderizar novamente o gráfico com quaisquer valores atualizados, permitindo que você edite o valor de vários pontos existentes e, em seguida, os renderize em um loop de renderização animado.

.addData( valuesArray, label )

Chamar addData (valuesArray, label) em sua instância do Chart passando uma matriz de valores para cada conjunto de dados, junto com um rótulo para esses pontos.

.removeData( )

Chamar removeData () em sua instância do gráfico removerá o primeiro valor de todos os conjuntos de dados no gráfico.

Todos esses são ótimos, mas não consigo descobrir como carregar um conjunto de dados inteiramente novo, eliminando o antigo. A documentação não parece cobrir isso.

tres
fonte

Respostas:

98

Eu tive grandes problemas com isso

Primeiro tentei, .clear()depois tentei .destroy()e tentei definir minha referência de gráfico como nula

O que finalmente resolveu o problema para mim: excluir o <canvas>elemento e reaplicar um novo <canvas>ao contêiner pai


Existem milhões de maneiras de fazer isso:

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);
};
neaumusic
fonte
20
Essa resposta funciona, mas descobri que destruir também funciona na versão mais recente. Recomendado nesta postagem - github.com/nnnick/Chart.js/issues/559
HockeyJ
ajudaria a esvaziar o div do container do gráfico para remover iframes antigos $ ('# results-graph'). remove (); $ ('# graph-container'). empty (); $ ('# graph-container'). append ('<canvas id = "results-graph"> <canvas>');
heyyan khan de
66

Você precisa destruir:

myLineChart.destroy();

Em seguida, reinicialize o gráfico:

var ctx = document.getElementById("myChartLine").getContext("2d");
myLineChart = new Chart(ctx).Line(data, options);
Krizenriquez
fonte
2
apenas use-o assim if (window.myLine) {window.myLine.destroy (); } OU if (myLineChart) {myLineChart.destroy (); }
jayant singh
Pode confirmar a destruição e, em seguida, a reinicialização não causa oscilação e parece que os pontos de dados foram atualizados dinamicamente
Titã
40

Com Chart.js V2.0, você pode fazer o seguinte:

websiteChart.config.data = some_new_data;
websiteChart.update();
luar
fonte
18
Exatamente o que a operação pediu.
Perry
2
Ao fazer chart.config.data = newDataisso, recebo este erro: TypeError: undefined is not an object (evaluating 'i.data.datasets.length') Alguém tem o mesmo problema?
Benjamin Lucidarme
21

É um tópico antigo, mas na versão atual (a partir de 01 de fevereiro de 2017), é fácil substituir conjuntos de dados plotados em chart.js:

Suponha que seus novos valores do eixo x estejam na matriz x e os valores do eixo y estejam na matriz y, você pode usar o código abaixo para atualizar o gráfico.

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

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

chart.update();
Pavan Kumar
fonte
Muito obrigado, cara! Desperdiçado o dia todo. Finalmente tropecei em sua resposta. Obrigado.
Dronacharya de
Isso foi útil e funcionou para mim. Mesmo usando apenas [] para definir um conjunto de dados vazio e, em seguida, fazer um novo "push" também resolverá o problema.
TS de
17

ChartJS 2.6 oferece suporte à substituição de referência de dados (consulte a nota na documentação de atualização (configuração)). Então, quando você tem seu gráfico, pode basicamente fazer isso:

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

Ele não faz a animação que você obteria ao adicionar pontos, mas os pontos existentes no gráfico serão animados.

Felix Jassler
fonte
12

Minha solução para isso é muito simples. (VERSÃO 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 ...

Sem oscilações ou problemas. getDataSeté uma função para controlar o conjunto de dados que preciso apresentar

Henrique C.
fonte
Você pode adicionar o snippet de código de getDataSet () também?
Gotham's Reckoning
1
Adicionado o exemplo getDataSet ()
Henrique C.
6

Segundo a docs, clear()limpa a tela. Pense nisso como a ferramenta Borracha no Paint. Não tem nada a ver com os dados carregados atualmente na instância do gráfico.

Destruir a instância e criar uma nova é um desperdício. Em vez disso, use métodos de API removeData()e addData(). Isso irá adicionar / remover um único segmento de / para a instância do gráfico. Portanto, se você deseja carregar dados completamente novos, apenas faça um loop em uma matriz de dados do gráfico e chame removeData(index)(os índices da matriz devem corresponder aos índices de segmento atuais). Em seguida, use addData(index)para preenchê-lo com os novos dados. Eu sugiro agrupar os dois métodos para fazer o loop dos dados, pois eles esperam um índice de segmento único. Eu uso resetCharte updateChart. Antes de continuar, certifique-se de verificar a Chart.jsversão e a documentação mais recentes. Eles podem ter adicionado novos métodos para substituir os dados completamente .

adi518
fonte
3
Gostei da sua resposta e é consistente com as informações que tenho lido online. Se você puder mostrar um exemplo, isso seria muito útil. Os dois exemplos que vi online que são semelhantes são: jsbin.com/yitep/5/edit?html,js,output e jsbin.com/yitep/4/edit?html,js,output
Rethabile
O único problema é que atualizar um gráfico se torna extremamente complicado e lento se você tiver que substituir os dados do gráfico por um conjunto de dados completamente diferente. Para começar, não encontrei uma maneira de atualizar os rótulos existentes do eixo x . Destruir e reinstanciar todo o gráfico é a única solução real em tais circunstâncias.
deceze
Infelizmente, lidei apenas com um gráfico Donut, que é menos complexo. Você verificou a API mais recente?
adi518 de
4

Encontrei o mesmo problema, tenho 6 gráficos de pizza em uma página que podem ser atualizados ao mesmo tempo. Estou usando a seguinte função para redefinir os dados do gráfico.

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

Piper0804
fonte
Embora isso funcione, descobri que é muito mais lento (devido à animação ao adicionar cada ponto) em comparação com a recriação do gráfico por completo.
Danila Vershinin
3

Tentei uma solução neaumusic , mas depois descobri que o único problema com destroy é o escopo .

var chart;

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

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

Mover a variável do meu gráfico para fora do escopo da função fez com que funcionasse para mim.

lony
fonte
3

Nenhuma das respostas acima ajudou minha situação particular de uma maneira muito limpa com o mínimo de código. Eu precisava remover todos os conjuntos de dados e, em seguida, fazer um loop para adicionar vários conjuntos de dados dinamicamente. Portanto, este recorte é para aqueles que chegam ao fim da página sem encontrar a resposta :)

Nota: certifique-se de chamar chart.update () depois de carregar todos os seus novos dados no objeto dataset. Espero que isso ajude alguém

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

function addData(chart, data) {
  chart.data.datasets.push(data);
}
Connor Crawford
fonte
2

Você precisa limpar dados antigos. Não há necessidade de reinicializar:

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

Se alguém estiver procurando como fazer isso em React. Para um gráfico de linha, supondo que você tenha um componente de invólucro ao redor do gráfico:

(Isso pressupõe que você está usando a v2. Você não precisa usar react-chartjs. Isso está usando o chart.jspacote normal do 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>
  );
}

A componentDidUpdatefuncionalidade permite que você atualize, adicione ou remova quaisquer dados do this.props.data.

Matthew Herbst
fonte
1

Não é necessário destruir o gráfico. Tente com isso

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();
    }
Jose Andres Beltran Ruiz
fonte
1

Aprenda como Chart.js (versão 2 aqui) funciona e faça-o para qualquer atributo que desejar:


1. Suponha que você tenha um gráfico de barras como o abaixo em seu HTML:

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

2. Suponha que você tenha um código javascript que preenche seu gráfico pela primeira vez (por exemplo, quando a página é carregada):

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

Suponha que você deseja atualizar totalmente seu conjunto de dados. É muito simples. Por favor, olhe para o código acima e veja como é o caminho de sua variável de gráfico para os dados e siga o caminho abaixo:

  • selecionar chartInstance var.
  • Em seguida, selecione data nodedentro dochartInstance .
  • Em seguida, selecione datasets nodedentro de data node.
    (nota: como você pode ver, datasets nodeé uma matriz. portanto, você deve especificar qual elemento dessa matriz deseja. aqui, temos apenas um elemento nodatasets node . portanto, usamosdatasets[0]
  • Então selecione datasets[0]
  • Em seguida, selecione data nodedentro do datasets[0].


Estas etapas fornecem chartInstance.data.datasets[0].datae você pode definir novos dados e atualizar o gráfico:

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


Nota: Seguindo o algoritmo acima, você pode simplesmente atingir cada nó desejado .

Ghasem Sadeghi
fonte
0

A única solução que posso encontrar até agora é reinicializar o gráfico do zero:

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

No entanto, isso parece um pouco piegas para mim. Alguma solução melhor e mais padrão?

tres
fonte
1
Isso funciona muito bem para mim, exceto que você precisa primeiro fazer myLineChart.destroy () para se livrar do antigo ou você terá um piscar enquanto ele é redesenhado.
user3413723
0

Eu também tive muitos problemas com isso. Eu tenho dados e rótulos em matrizes separadas e, em seguida, reinicializo os dados do gráfico. Eu adicionei o line.destroy (); como sugerido acima, que funcionou bem

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

Paulo
fonte
0

Não é uma maneira de fazer isso sem limpar a tela ou começar de novo, mas você tem que pega o homem a criação do gráfico para que os dados estão no mesmo formato para quando você atualizar.

Aqui está como eu fiz.

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

Basicamente, descarto os dados carregados na criação e, em seguida, faço a reforma com o método de adição de dados. Isso significa que posso acessar todos os pontos. Sempre que tento acessar a estrutura de dados criada por:

Chart(ctx).Bar(dataNew);

comando, não consigo acessar o que preciso. Isso significa que você pode alterar todos os pontos de dados, da mesma forma que os criou, e também chamar update () sem animar completamente do zero.

Simon Unsworth
fonte
0

Chart JS 2.0

Basta definir chart.data.labels = [];

Por exemplo:

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();
Kevin van Boeckholtz
fonte
0

Ao criar o objeto gráfico, você precisa salvar a instância em uma variável.

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

E antes de carregar novos dados, você precisa destruí- los:

currentChart.destroy();
omzer
fonte