ホバーイベントがトリガーされないようにキャンバスからチャートをクリアする方法は?


109

Chartjsを使用して折れ線グラフを表示していますが、これは正常に機能します。

// get line chart canvas
var targetCanvas = document.getElementById('chartCanvas').getContext('2d');

// draw line chart
var chart = new Chart(targetCanvas).Line(chartData);

しかし、チャートのデータを変更しようとすると問題が発生します。新しいデータポイントでChartの新しいインスタンスを作成し、キャンバスを再初期化してグラフを更新します。

これは正常に動作します。ただし、新しいグラフにカーソルを合わせると、古いグラフに表示されているポイントに対応する特定の場所に移動すると、ホバー/ラベルがトリガーされ、突然古いグラフが表示されます。マウスがこの場所にある間は表示されたままで、そのポイントから離れると消えます。古いグラフを表示したくない。完全に削除したい。

新しいものをロードする前に、キャンバスと既存のグラフの両方をクリアしようとしました。お気に入り:

targetCanvas.clearRect(0,0, targetCanvas.canvas.width, targetCanvas.canvas.height);

そして

chart.clear();

しかし、これらのどれも今のところ機能していません。これを防ぐにはどうすればいいですか?


18
おい、これはまさに私が抱えている問題です。「destroy()」メソッドは機能せず、うんざりしています。
neaumusic 14

グラフオブジェクトにアクセスする方法を教えてください。同じ問題が発生しています。チャートを作成し、ボタンクリックの処理時にそれを破棄する必要がありますが、それはまったく別の機能であり、キャンバスまたはコンテキストを介してチャートオブジェクトにアクセスする方法を見つけることができません。オブジェクト。
Matt Williams

この問題には未解決のバグがあります。こちらをご覧ください。github.com/jtblin/angular-chart.js/issues/187
MDT

この問題がありました。stackoverflow.com/a/51882403/1181367
Chris

回答:


142

私はこれで大きな問題を抱えていました

最初に試し.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');
  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);
};

2
チャンピオンのように働いた。Chart.jsバージョン2でこれが修正されるかどうか誰かが知っている場合は、ここに投稿してください。destroyが壊れているのか、それとも間違って使用しているのかしら。
TheLettuceMaster 2015年

2
いいね!ありがとう!$( '#results-graph')。remove();を追加しました。$( '#graph-container')。append( '<canvas id = "results-graph"> <canvas>'); チャート作成前。
イグナシオ

.destroy()は正常に動作するはずです。そうでない場合は、.destroy()を呼び出して新しいグラフを描画した後、setTimeout()を使用します。
Sumeet Kale

それは私にとって多くのおかげでうまくいった唯一の解決策ですが、幅と高さについては、すでに設定済みの場合はリセット機能で同じ値にリセットする必要があります
Sandy Elkassar

2
destroy()はchartjs 2.8.0で失敗しましたが、あなたのソリューションはうまくいきました!私の場合、私は$('#results-graph').remove(); $('#graph-container').append('<canvas id="results-graph"><canvas>');前にのみ使用しましたnew Chart(document.getElementById("myCanvas")
mimi

40

私は数時間前に同じ問題に直面しました。

".clear()"メソッドは実際にはキャンバスをクリアしますが、(明らかに)オブジェクトを生きたまま反応させます。

「高度な使用法」セクションの公式ドキュメントをよく読んで、次のように記述されているメソッド「.destroy()」に気づきました。

「これを使用して、作成されたすべてのチャートインスタンスを破棄します。これにより、Chart.jsによってアタッチされた関連するイベントリスナーとともに、Chart.js内のチャートオブジェクトに保存された参照がクリーンアップされます。」

それは実際にそれが主張することを行い、それは私にとってはうまくいきました、私はあなたにそれを試してみることを勧めます。


例を示してもらえますか?ブロッキングを複数回使用しようとしましたが、機能しません。メソッドが存在しないというエラーが常に表示されます。
ベンホフマン

3
(<ChartInstance> this.chart).destroy();
David Dal Busco 2016年

2
これは正しい答えです。今後の参考情報については、stackoverflow.com
questions / 40056555 /…を

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

1
これが最良の代替案です
RafaSashi 2016年

いいね。ありがとう
Manjunath Siddappa 2018年

11

これは私のために働いた唯一のものです:

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

9

ここでも同じ問題がありました... destroy()およびclear()メソッドを使用しようとしましたが、成功しませんでした。

私はそれを次の方法で解決しました:

HTML:

<div id="pieChartContent">
    <canvas id="pieChart" width="300" height="300"></canvas>
</div>

JavaScript:

var pieChartContent = document.getElementById('pieChartContent');
pieChartContent.innerHTML = '&nbsp;';
$('#pieChartContent').append('<canvas id="pieChart" width="300" height="300"><canvas>');

ctx = $("#pieChart").get(0).getContext("2d");        
var myPieChart = new Chart(ctx).Pie(data, options);

それは私にとって完璧に動作します...それが役に立てば幸いです。


5

これは私にとって非常にうまくいきました

    var ctx = $("#mycanvas");
     var LineGraph = new Chart(ctx, {
        type: 'line',
        data: chartdata});
        LineGraph.destroy();

.destroy thisを使用して、作成されたグラフインスタンスを破棄します。これにより、Chart.jsによってアタッチされた関連するイベントリスナーとともに、Chart.js内のチャートオブジェクトに格納されている参照がクリーンアップされます。これは、キャンバスを新しいチャートで再利用する前に呼び出す必要があります。


この方法は私にとって適切に機能し、ホバーコールバックを破壊するように見えます。戦車すごい!!
Antoine Pointeau 2016

4

Chart.js V2.0のグラフデータを次のように更新できます。

var myChart = new Chart(ctx, data);
myChart.config.data = new_data;
myChart.update();

私はこれがはるかに優れた解決策であることに同意します-「データ」を再起動することだけが本当に必要な場合、Destroyは非常に過激すぎます。
TS

1

CanvasJSを使用すると、これは私がチャートやその他すべてをクリアするのに役立ち、他の場所で処理する前にキャンバス/チャートを完全に設定することを許可してくれるでしょう:

var myDiv= document.getElementById("my_chart_container{0}";
myDiv.innerHTML = "";

私にとっては上記の方法のどれもうまくいきませんでした。これは完全に機能しました。どうもありがとう。
初心者

1

.destroy()も動作しないので、これは私がやっていることです。chart_parent divは、キャンバスを表示する場所です。毎回キャンバスのサイズを変更する必要があるので、この答えは上記の拡張です。

HTML:

<div class="main_section" > <div id="chart_parent"></div> <div id="legend"></div> </div>

jQuery:

  $('#chart').remove(); // this is my <canvas> element
  $('#chart_parent').append('<label for = "chart">Total<br /><canvas class="chart" id="chart" width='+$('#chart_parent').width()+'><canvas></label>');

1

1つの新しいchart.jsキャンバスを作成すると、1つの新しいiframeが非表示になり、キャンバスと古いiframeを削除する必要があります。

$('#canvasChart').remove(); 
$('iframe.chartjs-hidden-iframe').remove(); 
$('#graph-container').append('<canvas id="canvasChart"><canvas>'); 
var ctx = document.getElementById("canvasChart"); 
var myChart = new Chart(ctx, { blablabla });

参照:https : //github.com/zebus3d/javascript/blob/master/chartJS_filtering_with_checkboxs.html


1

これでうまくいきました。clearChartの呼び出しを、updateChart()の上部に追加します。

`function clearChart() {
    event.preventDefault();
    var parent = document.getElementById('parent-canvas');
    var child = document.getElementById('myChart');          
    parent.removeChild(child);            
    parent.innerHTML ='<canvas id="myChart" width="350" height="99" ></canvas>';             
    return;
}`

1

Typescriptを使用するAngularプロジェクトでchart.jsを使用している場合は、以下を試すことができます。

Import the library:
    import { Chart } from 'chart.js';

In your Component Class declare the variable and define a method:

  chart: Chart;

  drawGraph(): void {
    if (this.chart) {
      this.chart.destroy();
    }

    this.chart = new Chart('myChart', {
       .........
    });
  }


In HTML Template:
<canvas id="myChart"></canvas>

1

新しいチャートを初期化する前に、プレビューチャートインスタンスが既に存在する場合は削除または破棄し、次に新しいチャートを作成します。

if(myGraf != undefined)
    myGraf.destroy();
    myGraf= new Chart(document.getElementById("CanvasID"),
    { 
      ...
    }

お役に立てれば。


1

アダムの答えを補完する

バニラJSで:

document.getElementById("results-graph").remove(); //canvas
div = document.querySelector("#graph-container"); //canvas parent element
div.insertAdjacentHTML("afterbegin", "<canvas id='results-graph'></canvas>"); //adding the canvas again


1

2020年の簡単な編集:

これでうまくいきました。ウィンドウを所有するようにして、グラフをグローバルに変更します(宣言をからvar myChartに変更しますwindow myChart

グラフ変数がすでにChartとして初期化されているかどうかを確認します。初期化されている場合は、それを破棄して新しい変数を作成します。同じ名前で別の変数を作成することもできます。以下はコードです:

if(window.myChart instanceof Chart)
{
    window.myChart.destroy();
}
var ctx = document.getElementById('myChart').getContext("2d");

うまくいきますように!


1
どうもありがとう。これでうまくいきます。
ダンテ

0

私にとってこれはうまくいきました:

		var in_canvas = document.getElementById('chart_holder');
	//remove canvas if present
			while (in_canvas.hasChildNodes()) {
				  in_canvas.removeChild(in_canvas.lastChild);
				} 
	//insert canvas
			var newDiv = document.createElement('canvas');
			in_canvas.appendChild(newDiv);
			newDiv.id = "myChart";


0

Chart.jsにはバグがあります。 Chart.controller(instance)ます。新しいグラフをグローバルプロパティに登録Chart.instances[]し、このプロパティから削除します。.destroy()ます。

しかし、チャートの作成時に、Chart.jsも書き込みます ._metaプロパティをデータセット変数にます。

var meta = dataset._meta[me.id];
if (!meta) {
   meta = dataset._meta[me.id] = {
       type: null,
       data: [],
       dataset: null,
       controller: null,
       hidden: null,     // See isDatasetVisible() comment
       xAxisID: null,
       yAxisID: null
   };

このプロパティは削除されません destroy()

削除せずに古いデータセットオブジェクトを使用する場合 ._meta property、Chart.jsは新しいデータセットを._meta以前のデータを削除せずにます。したがって、各グラフの再初期化時に、データセットオブジェクトは以前のすべてのデータを蓄積します。

これを回避するには、を呼び出しChart.destroy()た後にデータセットオブジェクトを破棄します。


0

destroyは一種の「すべて」を破壊するので、本当に必要なのは「データをリセット」するだけの安価でシンプルなソリューションです。データセットを空の配列にリセットしても、まったく問題なく動作します。したがって、ラベル付きのデータセットがあり、両側に軸がある場合:

window.myLine2.data.labels = [];
window.myLine2.data.datasets[0].data = [];
window.myLine2.data.datasets[1].data = [];

この後、単に呼び出すことができます:

window.myLine2.data.labels.push(x);
window.myLine2.data.datasets[0].data.push(y);

または、2Dデータセットを使用しているかどうかによって異なります。

window.myLine2.data.datasets[0].data.push({ x: x, y: y});

チャート/データセット全体を完全に破棄してすべてを再構築するよりも、はるかに軽量になります。


0

私のような関数を使用して複数のグラフィックを作成し、それらもブロックで更新したい人にとっては、関数.destroy()だけが私のために機能し、私は.update()を作成したいと思ったでしょう。 。ここに役立つコードスニペットがあります。

var SNS_Chart = {};

// IF LABELS IS EMPTY (after update my datas)
if( labels.length != 0 ){

      if( Object.entries(SNS_Chart).length != 0 ){

            array_items_datas.forEach(function(for_item, k_arr){
                SNS_Chart[''+for_item+''].destroy();
            });

       }

       // LOOP OVER ARRAY_ITEMS
       array_items_datas.forEach(function(for_item, k_arr){

             // chart
             OPTIONS.title.text = array_str[k_arr];
             var elem = document.getElementById(for_item);
             SNS_Chart[''+for_item+''] = new Chart(elem, {
                 type: 'doughnut',
                 data: {
                     labels: labels[''+for_item+''],
                     datasets: [{
                        // label: '',
                        backgroundColor: [
                            '#5b9aa0',
                            '#c6bcb6',
                            '#eeac99',
                            '#a79e84',
                            '#dbceb0',
                            '#8ca3a3',
                            '#82b74b',
                            '#454140',
                            '#c1502e',
                            '#bd5734'
                        ],
                        borderColor: '#757575',
                        borderWidth : 2,
                        // hoverBackgroundColor : '#616161',
                        data: datas[''+for_item+''],
                     }]
                 },
                 options: OPTIONS

             });
             // chart
       });
       // END LOOP ARRAY_ITEMS

  }
 // END IF LABELS IS EMPTY ...
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.