web-dev-qa-db-ja.com

ホバリング時に古いデータを示すChartjs棒グラフ

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

元のデータを破棄して、日付範囲を変更して新しいチャートにカーソルを合わせたときに、古いデータがちらつかないようにする最良の方法は何ですか?

ありがとう

21
Djones12

あなたが取っているアプローチ(たとえば、日付範囲が変わるたびに新しいChartオブジェクトを作成する)では、最初に前のチャートを破棄してから新しいチャートを作成する必要があります。

.destroy() prototypeメソッドを使用してこれを行うことができます。これが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,
              }]
            }
          }
        });
      }
    });
}
_
34
jordanwillis

これは私が見つけたchartjsのトリックです

var ctxLine = document.getElementById("line-chart").getContext("2d");
if(window.bar != undefined) 
window.bar.destroy(); 
window.bar = new Chart(ctxLine, {});

https://therichpost.com/solved-hovering-chartjs-bar-chart-showing-old-data

6
Rodener Dajes

それはあなたを助けます...

MyChartがすでに設定されているかどうかを確認します。存在する場合はdestroy()でクリアします。メソッド、および新しい構成をキャンバスにバインドします。

サンプルコード..

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

これには、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");

これで問題が解決しました。

1
Rajeshwar

私は問題を発見し、私の解決策は最初に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>
1

Chartjs.orgが提供するサンプルのコードは、チャートを破棄()して新しいチャートを作成しないことを示しています。代わりに、チャートから既存のデータをpop()し、新しいデータセットをグラフにPush()してからチャートをupdate()します。

このコードは、POP()によってチャートからデータセットを削除するchartjs.org Webサイトからのものです。

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

これら2つのコードブロックの最後の手順は、チャートを更新することです。

一般的に、チャートから削除するデータをポップしてから、新しいデータをプッシュし、最後にチャートを更新する必要があります。したがって、ホバリング時に以前のデータは表示されません。

0
Reza