chart.js загружает совершенно новые данные


87

API дляchart.js позволяет редактировать точки загруженных в него наборов данных, например:

.update( )

Вызов update () в вашем экземпляре Chart повторно визуализирует диаграмму с любыми обновленными значениями, что позволяет вам редактировать значение нескольких существующих точек, а затем визуализировать их в одном анимированном цикле визуализации.

.addData( valuesArray, label )

Вызов addData (valuesArray, label) в экземпляре Chart с передачей массива значений для каждого набора данных вместе с меткой для этих точек.

.removeData( )

Вызов removeData () в вашем экземпляре Chart удалит первое значение для всех наборов данных на диаграмме.

Все это здорово, но я не могу понять, как загрузить совершенно новый набор данных, удалив старый. Документация, похоже, не охватывает этого.

Ответы:


98

У меня были огромные проблемы с этим

Сначала я попробовал, .clear()потом попробовал, .destroy()и попытался установить для ссылки на диаграмму значение null

Что окончательно <canvas>устранило для меня проблему: удаление элемента и повторное добавление нового <canvas>в родительский контейнер


Есть миллион способов сделать это:

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
Этот ответ работает, но я обнаружил, что уничтожение также работает в последней версии. Рекомендовано в этом посте - github.com/nnnick/Chart.js/issues/559
HockeyJ

это поможет пустому div-контейнеру графа удалить старые фреймы $ ('# results-graph'). remove (); $ ('# граф-контейнер'). empty (); $ ('# граф-контейнер'). append ('<canvas id = "results-graph"> <canvas>');
heyyan khan

66

Вам нужно уничтожить:

myLineChart.destroy();

Затем повторно инициализируйте диаграмму:

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

2
просто используйте это так if (window.myLine) {window.myLine.destroy (); } ИЛИ если (myLineChart) {myLineChart.destroy (); }
джаянт сингх

Может подтвердить уничтожение, а затем повторная инициализация не вызывает мерцания и выглядит так, как будто точки данных были динамически обновлены
Titan

40

С Chart.js V2.0 вы можете делать следующее:

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

18
Именно то, о чем просила опера.
Перри

2
Когда я это делаю chart.config.data = newData, у меня появляется такая ошибка: у TypeError: undefined is not an object (evaluating 'i.data.datasets.length') кого-то такая же проблема?
Benjamin Lucidarme

21

Это старый поток, но в текущей версии (по состоянию на 1 февраля 2017 г.) легко заменить наборы данных, построенные на chart.js:

предположим, что ваши новые значения оси x находятся в массиве x, а значения оси y находятся в массиве y, вы можете использовать приведенный ниже код для обновления диаграммы.

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

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

chart.update();

Большое спасибо, чувак! Зря потратил весь день. Наконец-то наткнулся на свой ответ. Спасибо.
Dronacharya

Это было полезно и помогло мне. Даже простое использование [] для установки пустого набора данных с последующим повторным «толчком» тоже поможет.
TS

17

ChartJS 2.6 поддерживает замену ссылок на данные (см. Примечание в документации по обновлению (конфигурации)). Итак, когда у вас есть диаграмма, вы можете просто сделать это:

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

Он не выполняет анимацию, которую вы получили бы при добавлении точек, но существующие точки на графике будут анимированы.


12

Мое решение этой проблемы довольно простое. (ВЕРСИЯ 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 ...

Никакого мерцания или проблем. getDataSetэто функция для управления набором данных, который мне нужно представить


Можете ли вы также добавить фрагмент кода getDataSet ()?
Gotham's Reckoning

1
Добавлен пример getDataSet ()
Henrique C.

8

Я ответил на это здесь, см. Как очистить диаграмму с холста, чтобы события зависания не запускались?

Но вот решение:

var myPieChart=null;

function drawChart(objChart,data){
    if(myPieChart!=null){
        myPieChart.destroy();
    }
    // Get the context of the canvas element we want to select
    var ctx = objChart.getContext("2d");
    myPieChart = new Chart(ctx).Pie(data, {animateScale: true});
}

6

Согласно документам, clear()очищает холст. Думайте об этом как об инструменте Eraser в Paint. Это не имеет ничего общего с данными, загруженными в данный момент в экземпляр диаграммы.

Уничтожение экземпляра и создание нового бесполезно. Вместо этого используйте методы API removeData()и addData(). Это добавит / удалит один сегмент в / из экземпляра диаграммы. Поэтому, если вы хотите загрузить полностью новые данные, просто зациклите массив данных диаграммы и вызовите его removeData(index)(индексы массива должны соответствовать индексам текущего сегмента). Затем используйте, addData(index)чтобы заполнить его новыми данными. Я предлагаю обернуть два метода циклической обработки данных, поскольку они ожидают единого индекса сегмента. Пользуюсь resetChartи updateChart. Прежде чем продолжить, убедитесь, что вы проверили Chart.jsпоследнюю версию и документацию. Возможно, они добавили новые методы для полной замены данных .


3
Мне нравится ваш ответ, и он согласуется с информацией, которую я читал в Интернете. Если вы можете показать пример, это будет действительно полезно. Два похожих примера, которые я видел в Интернете: jsbin.com/yitep/5/edit?html,js,output и jsbin.com/yitep/4/edit?html,js,output
Rethabile

Единственная проблема заключается в том, что обновление диаграммы становится чрезвычайно громоздким и очень медленным, если вам нужно заменить данные диаграммы совершенно другим набором данных. Для начала, я не нашел способ обновления существующей х-ось этикетки . Уничтожение и восстановление всей диаграммы - единственное реальное решение в таких обстоятельствах.
deceze

К сожалению, я имел дело только с кольцевой диаграммой, которая менее сложна. Вы проверяли последнюю версию API?
adi518

4

Я столкнулся с той же проблемой, у меня на странице 6 круговых диаграмм, которые можно обновлять одновременно. Я использую следующую функцию для сброса данных диаграммы.

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


Хотя это работает, я обнаружил, что это намного медленнее (из-за анимации при добавлении каждой точки) по сравнению с воссозданием диаграммы в целом.
Данила Вершинин

3

Я попробовал решение neaumusic , но позже выяснил, что единственная проблема с уничтожением - это масштаб .

var chart;

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

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

Перемещение переменной диаграммы за пределы функции заставило меня работать.


3

Ни один из приведенных выше ответов не помог моей конкретной ситуации очень чисто с минимальным кодом. Мне нужно было удалить все наборы данных, а затем выполнить цикл для динамического добавления нескольких наборов данных. Так что это вырезано для тех, кто доходит до конца страницы, не находя ответа :)

Примечание: не забудьте вызвать chart.update () после того, как вы загрузили все свои новые данные в объект набора данных. Надеюсь, это кому-то поможет

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

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

2

Вам нужно очистить старые данные. Нет необходимости повторно инициализировать:

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

1

Если кто-то ищет как это сделать в React. Для линейной диаграммы, если у вас есть компонент-оболочка вокруг диаграммы:

(Предполагается, что вы используете версию 2. В этом нет необходимости react-chartjs. Используется обычный chart.jsпакет от 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>
  );
}

Эта componentDidUpdateфункция позволяет обновлять, добавлять или удалять любые данные из файла this.props.data.


1

Не обязательно уничтожать график. Попробуйте с этим

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

Узнайте, как работает Chart.js (версия 2 здесь), и сделайте это для любого атрибута, который хотите:


1. Предположим, у вас есть столбчатая диаграмма в HTML-коде, подобная приведенной ниже:

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

2. Предположим, у вас есть код javascript, который заполняет вашу диаграмму первый раз (например, при загрузке страницы):

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

Предположим, вы хотите полностью обновить свой набор данных. Все очень просто. Посмотрите на приведенный выше код и посмотрите, как проходит путь от переменной вашей диаграммы к данным, а затем следуйте указанному ниже пути:

  • выберите chartInstancevar.
  • Затем выберите data nodeвнутри chartInstance.
  • Затем выберите datasets nodeвнутри data node.
    (примечание: как вы можете видеть, datasets nodeэто массив. поэтому вы должны указать, какой элемент этого массива вам нужен. Здесь у нас есть только один элемент в datasets node. поэтому мы используемdatasets[0]
  • Так что выберите datasets[0]
  • Затем выберите data nodeвнутри в datasets[0].


Эти шаги дают вам, chartInstance.data.datasets[0].dataи вы можете установить новые данные и обновить диаграмму:

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


Примечание. Следуя приведенному выше алгоритму, вы можете просто достичь каждого нужного узла .


0

Единственное решение, которое я могу найти для себя, - это переинициализировать диаграмму с нуля:

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

Однако мне это кажется немного странным. Есть ли у кого-нибудь лучшее, более стандартное решение?


1
Это в значительной степени работает для меня, за исключением того, что вам нужно сначала выполнить myLineChart.destroy (), чтобы избавиться от старого, иначе у вас будет мерцание при перерисовке.
user3413723

0

У меня тоже было много проблем с этим. У меня есть данные и метки в отдельных массивах, после чего я повторно инициализирую данные диаграммы. Я добавил line.destroy (); как было предложено выше, что помогло

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


0

Там есть способ сделать это без очистки холста или начать сначала, но вы должны человек ручку создания диаграммы , так что данные в том же формате при обновлении.

Вот как я это сделал.

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

Я в основном отбрасываю данные, загруженные при создании, а затем реформирую с помощью метода добавления данных. Это означает, что я могу получить доступ ко всем точкам. Всякий раз, когда я пытался получить доступ к структуре данных, созданной:

Chart(ctx).Bar(dataNew);

команда, я не могу получить доступ к тому, что мне нужно. Это означает, что вы можете изменить все точки данных так же, как вы их создали, а также вызвать update () без полной анимации с нуля.


0

Диаграмма JS 2.0

Просто установите chart.data.labels = [];

Например:

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

При создании объекта диаграммы вам необходимо сохранить экземпляр в переменной.

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

И перед загрузкой новых данных нужно их уничтожить :

currentChart.destroy();
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.