web-dev-qa-db-fra.com

Comment effacer un graphique d'un canevas afin que des événements de survol ne puissent pas être déclenchés?

J'utilise Chartjs pour afficher un graphique en courbes et cela fonctionne bien:

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

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

Mais le problème survient lorsque j'essaie de modifier les données du graphique. Je met à jour le graphique en créant une nouvelle instance d'un graphique avec les nouveaux points de données et en réinitialisant ainsi le canevas. 

Cela fonctionne bien. Cependant, lorsque je survole la nouvelle carte, si je survole des emplacements spécifiques correspondant à des points affichés sur l'ancienne carte, le survol/libellé est toujours déclenché et, tout à coup, l'ancienne carte est visible. Il reste visible lorsque ma souris est à cet endroit et disparaît lorsque vous quittez ce point. Je ne veux pas que l'ancien graphique s'affiche. Je veux l'enlever complètement.

J'ai essayé d'effacer le canevas et le graphique existant avant de charger le nouveau. Comme:

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

et

chart.clear();

Mais aucun d’entre eux n’a fonctionné jusqu’à présent. Des idées sur la façon dont je peux empêcher cela de se produire?

84
Adam Jones

J'ai eu d'énormes problèmes avec ça

J'ai d'abord essayé .clear(), puis j'ai essayé .destroy() et j'ai essayé de définir la référence de mon graphique sur null

Ce qui a finalement résolu le problème pour moi: supprimer l'élément <canvas> puis ré-ajouter un nouveau <canvas> au conteneur parent


Mon code spécifique (évidemment, il existe un million de façons de le faire):

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

J'ai rencontré le même problème il y a quelques heures.

La méthode ".clear ()" efface réellement la toile, mais elle laisse (évidemment) l'objet en vie et réactif.

En lisant attentivement la documentation officielle , dans la section "Utilisation avancée", j'ai remarqué la méthode ".destroy ()", décrite comme suit:

"Utilisez-le pour détruire toutes les occurrences de graphique créées. Ceci nettoiera toutes les références stockées dans l'objet graphique dans Chart.js, Ainsi que tous les écouteurs d'événements associés attachés par Chart.js."

En fait, il fait ce qu’il prétend et cela a bien fonctionné pour moi, je vous suggère de l'essayer.

31
Roberto Pierpaoli
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});
}
23
xchiltonx

C'est la seule chose qui a fonctionné pour moi: 

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

J'ai eu le même problème ici ... J'ai essayé d'utiliser les méthodes destroy () et clear (), mais sans succès.

Je l'ai résolu le chemin suivant:

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

Cela fonctionne parfaitement pour moi ... J'espère que cela aide.

4
Javier Muñoz

Cela a très bien fonctionné pour moi

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

Utilisez .destroy this pour détruire toutes les instances de graphique créées. Cela nettoiera toutes les références stockées dans l'objet graphique dans Chart.js, ainsi que tous les écouteurs d'événements associés attachés par Chart.js. Cela doit être appelé avant que la toile ne soit réutilisée pour un nouveau graphique.

4
Nicholas Macharia

Nous pouvons mettre à jour les données de graphique dans Chart.js V2.0 comme suit:

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

Si vous utilisez chart.js dans un projet Angular avec TypeScript, vous pouvez essayer les solutions suivantes:

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>

Je ne pouvais pas faire fonctionner .destroy (), c’est ce que je suis en train de faire. La div chart_parent est l'endroit où je veux que la toile apparaisse. J'ai besoin de la toile pour la redimensionner à chaque fois, donc cette réponse est une extension de celle ci-dessus.

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
Chris

Avec CanvasJS, cela fonctionne pour moi, pour effacer les graphiques et tout le reste, mais également pour vous, en vous permettant de définir votre toile/graphique complètement avant chaque traitement ailleurs:

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

Lorsque vous créez un nouveau canevas chart.js, cela génère un nouveau iframe masqué, vous devez supprimer le canevas et les anciens iframes. 

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

référence: https://github.com/zebus3d/javascript/blob/master/chartJS_filtering_with_checkboxs.html

1
zebus3d

Comme détruire détruit en quelque sorte "tout", une solution simple et peu coûteuse, lorsque vous voulez vraiment, est simplement de "réinitialiser les données". Réinitialiser vos jeux de données sur un tableau vide fonctionnera également parfaitement. Donc, si vous avez un jeu de données avec des étiquettes et un axe de chaque côté:

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

Après cela, vous pouvez simplement appeler:

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

ou, selon que vous utilisez un jeu de données 2D:

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

Ce sera beaucoup plus léger que de détruire complètement tout votre graphique/jeu de données et de tout reconstruire.

0
T.S

Ce que nous avons fait est, avant l'initialisation du nouveau graphique, supprimer/détruire les aperçus Exemple de graphique, s'il existe déjà, puis créer un nouveau graphique, par exemple

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

J'espère que cela t'aides.

0
Qammar Feroz

Pour moi cela a fonctionné:

		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
Scrapie

Chart.js a un bogue: Chart.controller(instance) enregistre tout nouveau graphique dans une propriété globale Chart.instances[] et le supprime de cette propriété sur .destroy()

Mais lors de la création du graphique, Chart.js écrit également la propriété ._meta dans la variable d'ensemble de données:

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

et il ne supprime pas cette propriété sur destroy()

Si vous utilisez votre ancien objet de jeu de données sans supprimer ._meta property, Chart.js ajoutera un nouveau jeu de données à ._meta sans supprimer les données précédentes. Ainsi, lors de la réinitialisation de chaque graphique, votre objet de jeu de données accumule toutes les données précédentes.

Afin d'éviter cela, détruisez l'objet de jeu de données après avoir appelé Chart.destroy().

0
Andrew Hudik

Cela a fonctionné pour moi . Ajouter un appel à clearChart, en haut de votre 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;
}`
0
Jay