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

87

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

.update( )

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

.addData( valuesArray, label )

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

.removeData( )

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

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

dthree
источник

Ответы:

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});
}
xchiltonx
источник
6

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

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

adi518
источник
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();

Piper0804
источник
Хотя это работает, я обнаружил, что это намного медленнее (из-за анимации при добавлении каждой точки) по сравнению с воссозданием диаграммы в целом.
Данила Вершинин
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);

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

dthree
источник
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();
омзер
источник