Chartjs Bar Chart, показывающая старые данные при зависании

У меня есть диаграмма, созданная с использованием chart.js. Все работает нормально при загрузке страницы, но когда я изменяю временной интервал с помощью daterangepicker, появляется глюк. Новые данные вводятся, но когда я наводил на него курсор, отображаются старые данные. Я новичок в javascript, поэтому я надеюсь получить помощь. Похоже, мне нужно включить.destroy(); так или иначе, но я не знаю, как это сделать. Ниже приведен фрагмент моего кода:

function loadFTPRChart(startdate, enddate){
var BCData = {
labels: [],
datasets: [
 {
  label: "Pass %",
  backgroundColor: "#536A7F",
  data: [],
  stack: 1
},
{
  label: "Fail %",
  backgroundColor: "#e6e6e6",
  data: [],
  stack: 1
},
{
  label: "Auto %",
  backgroundColor: "#286090",
  data: [],
  stack: 2
},
{
  label: "Manual %",
  backgroundColor: "#f0f0f0",
  data: [],
  stack: 2
}
 ]
};
  $.getJSON( "content/FTPR_AM_Graph_ajax.php", {
    startdate: startdate,
    enddate: enddate,
    location: "M"
})
.done(function( data ) {
    console.log("data", data);
    $.each( data.aaData, function( key, val ) {
      if(val == ""){return true}
      BCData.labels.push("Coater " + val[0]);
      BCData.datasets[0].data.push(parseFloat(val[2]));
      BCData.datasets[1].data.push(parseFloat(100-val[2]));
      BCData.datasets[2].data.push(parseFloat(val[1]));
      BCData.datasets[3].data.push(parseFloat(100-val[1]));
    });

    var option = {   
     responsive:true,
};
console.log("BCData", BCData);


//console.log("PrevData", data);
var ctx = document.getElementById("mybarChart2").getContext("2d");
new Chart(ctx, {
  type: 'groupableBar',
  data: BCData,
  options: {
    scales: {
      yAxes: [{
        ticks: {
          max: 100,
        },
        stacked: true,
      }]
    }
  }
});
});

}


loadFTPRChart($('#reportrange').data().daterangepicker.startDate.format('MM/DD/YYYY'), $('#reportrange').data().daterangepicker.endDate.format('MM/DD/YYYY'));

Каков наилучший способ уничтожить исходные данные, чтобы при изменении диапазона дат и наведении на новую диаграмму старые данные больше не мерцали?

благодаря

Ответ 1

При подходе, который вы предпринимаете (например, при создании нового объекта диаграммы каждый раз, когда изменяется диапазон дат), вы должны сначала уничтожить предыдущую диаграмму, а затем создать новую.

Для этого вы можете использовать метод прототипа .destroy(). Вот что говорит API.

Используйте это, чтобы уничтожить созданные экземпляры диаграмм. Это очистит любые ссылки, хранящиеся в объекте диаграммы в Chart.js, а также любые связанные с ними прослушиватели событий, прикрепленные Chart.js. Это нужно вызвать до того, как холст будет повторно использован для новой диаграммы.

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

// define a variable to store the chart instance (this must be outside of your function)
var myChart;

function loadFTPRChart(startdate, enddate) {
  var BCData = {
    labels: [],
    datasets: [{
      label: "Pass %",
      backgroundColor: "#536A7F",
      data: [],
      stack: 1
    }, {
      label: "Fail %",
      backgroundColor: "#e6e6e6",
      data: [],
      stack: 1
    }, {
      label: "Auto %",
      backgroundColor: "#286090",
      data: [],
      stack: 2
    }, {
      label: "Manual %",
      backgroundColor: "#f0f0f0",
      data: [],
      stack: 2
    }]
  };

  $.getJSON("content/FTPR_AM_Graph_ajax.php", {
      startdate: startdate,
      enddate: enddate,
      location: "M"
    })
    .done(function(data) {
      console.log("data", data);
      $.each(data.aaData, function(key, val) {
        if (val == "") {
          return true
        }
        BCData.labels.push("Coater " + val[0]);
        BCData.datasets[0].data.push(parseFloat(val[2]));
        BCData.datasets[1].data.push(parseFloat(100 - val[2]));
        BCData.datasets[2].data.push(parseFloat(val[1]));
        BCData.datasets[3].data.push(parseFloat(100 - val[1]));
      });

      var option = {
        responsive: true,
      };
      console.log("BCData", BCData);

      // if the chart is not undefined (e.g. it has been created)
      // then destory the old one so we can create a new one later
      if (myChart) {
        myChart.destroy();
      }

      var ctx = document.getElementById("mybarChart2").getContext("2d");
      myChart = new Chart(ctx, {
        type: 'groupableBar',
        data: BCData,
        options: {
          scales: {
            yAxes: [{
              ticks: {
                max: 100,
              },
              stacked: true,
            }]
          }
        }
      });
    });
}

С учетом сказанного это дорого разрушает/создает снова и снова, и на самом деле это даже не нужно. Существует еще один метод прототипа, называемый .update() который вы можете использовать, чтобы просто перерисовать диаграмму, если вы изменили ее на базовые данные или объекты метки.

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

Вот как будет выглядеть ваш код с таким лучшим подходом.

// define a variable to store the chart instance (this must be outside of your function)
var myChart;

function loadFTPRChart(startdate, enddate) {
  var BCData = {
    labels: [],
    datasets: [{
      label: "Pass %",
      backgroundColor: "#536A7F",
      data: [],
      stack: 1
    }, {
      label: "Fail %",
      backgroundColor: "#e6e6e6",
      data: [],
      stack: 1
    }, {
      label: "Auto %",
      backgroundColor: "#286090",
      data: [],
      stack: 2
    }, {
      label: "Manual %",
      backgroundColor: "#f0f0f0",
      data: [],
      stack: 2
    }]
  };

  $.getJSON("content/FTPR_AM_Graph_ajax.php", {
      startdate: startdate,
      enddate: enddate,
      location: "M"
    })
    .done(function(data) {
      console.log("data", data);
      $.each(data.aaData, function(key, val) {
        if (val == "") {
          return true
        }
        BCData.labels.push("Coater " + val[0]);
        BCData.datasets[0].data.push(parseFloat(val[2]));
        BCData.datasets[1].data.push(parseFloat(100 - val[2]));
        BCData.datasets[2].data.push(parseFloat(val[1]));
        BCData.datasets[3].data.push(parseFloat(100 - val[1]));
      });

      var option = {
        responsive: true,
      };
      console.log("BCData", BCData);

      // if the chart is not undefined (e.g. it has been created)
      // then just update the underlying labels and data for each
      // dataset and re-render the chart
      if (myChart) {
        myChart.data.labels = BCData.labels;
        myChart.data.datasets[0].data = BCData.datasets[0].data;
        myChart.data.datasets[1].data = BCData.datasets[1].data;
        myChart.data.datasets[2].data = BCData.datasets[2].data;
        myChart.data.datasets[3].data = BCData.datasets[3].data;
        myChart.update();
      } else {
        // otherwise, this is the first time we are loading so create the chart
        var ctx = document.getElementById("mybarChart2").getContext("2d");
        myChart = new Chart(ctx, {
          type: 'groupableBar',
          data: BCData,
          options: {
            scales: {
              yAxes: [{
                ticks: {
                  max: 100,
                },
                stacked: true,
              }]
            }
          }
        });
      }
    });
}

Ответ 2

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

Html

 $('#chart').empty();
    
$('#chart').html('<canvas id="survey_result"  width="400" height="200"></canvas>'); // then load chart.
    
var ctx = document.getElementById("survey_result");
    <div id="chart" class="display>
    </div>

Ответ 3

Для этого есть простое решение, которое можно сделать в самой JS.

скажем, у вашего html есть что-то вроде ниже

<div id="chartContainer">
 <canvas id="mybarChart2"></canvas>
</div>

Затем в вашем скрипте вы можете добавить строки ниже кода перед обновлением данных.

document.getElementById("chartContainer").innerHTML = '&nbsp;';
document.getElementById("chartContainer").innerHTML = '<canvas id="mybarChart2"></canvas>';
var ctx = document.getElementById("mybarChart2").getContext("2d");

Это решило мою проблему.

Ответ 5

Это поможет вам...

Проверьте, есть ли у MyChart уже конфигурации или нет, если он существует, очистите его с помощью destroy(); метод, и привязать новую конфигурацию к холсту.

Образец кода..

if (window.MyChart != undefined)
{
    window.MyChart.destroy();
}
window.MyChart = new Chart(ctx, MyChartconfig);

Ответ 6

Код предоставленных примеров от chartjs.org показал, что они не разрушают() диаграмму и не создают новую. Вместо этого они выталкивают() существующие данные из диаграммы и помещают() новый набор данных в график, а затем обновляют() диаграмму.

Этот код взят с веб-сайта chartjs.org, который удаляет набор данных из диаграммы с помощью POP().

    document.getElementById('removeDataset').addEventListener('click', function() {
        horizontalBarChartData.datasets.pop();
        window.myHorizontalBar.update();
    });

И этот код для добавления набора данных в диаграмму с помощью PUSH():

    document.getElementById('addDataset').addEventListener('click', function() {
        var colorName = colorNames[horizontalBarChartData.datasets.length % colorNames.length];
        var dsColor = window.chartColors[colorName];
        var newDataset = {
            label: 'Dataset ' + (horizontalBarChartData.datasets.length + 1),
            backgroundColor: color(dsColor).alpha(0.5).rgbString(),
            borderColor: dsColor,
            data: []
        };

        for (var index = 0; index < horizontalBarChartData.labels.length; ++index) {
            newDataset.data.push(randomScalingFactor());
        }

        horizontalBarChartData.datasets.push(newDataset);
        window.myHorizontalBar.update();
    });

Последний шаг этих двух блоков кода - обновить диаграмму.

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