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

109

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 se produit lorsque j'essaie de modifier les données du graphique. Je mets à 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 très bien. Cependant, lorsque je survole le nouveau graphique, s'il m'arrive de passer par des emplacements spécifiques correspondant aux points affichés sur l'ancien graphique, le survol / l'étiquette est toujours déclenché et soudainement l'ancien graphique est visible. Il reste visible tant que ma souris est à cet endroit et disparaît lorsque je quitte ce point. Je ne veux pas que l'ancien graphique s'affiche. Je veux le supprimer complètement.

J'ai essayé d'effacer à la fois 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 de ceux-ci n'a fonctionné jusqu'à présent. Des idées sur la façon dont je peux empêcher cela de se produire?

Adam Jones
la source
18
Mec, c'est exactement le problème que j'ai. La méthode "destroy ()" ne fonctionne pas et ça me fait chier.
neaumusic
Puis-je vous demander comment vous accédez à l'objet graphique? J'ai le même problème, je crée un graphique, puis sur la manipulation d'un bouton, cliquez sur je dois le détruire, mais c'est dans une fonction entièrement différente et je ne trouve pas de moyen d'accéder à l'objet graphique via le canevas ou le contexte objets.
Matt Williams
Il y a un bug ouvert pour ce problème, voyez-le ici. github.com/jtblin/angular-chart.js/issues/187
MDT
Eu ce problème. Solution pour créer / recréer stackoverflow.com/a/51882403/1181367
Chris

Réponses:

143

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 ma référence de graphique sur null

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


Mon code spécifique (il y a évidemment 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);
};
neaumusic
la source
2
A travaillé comme un champion. Si quelqu'un sait si la version 2 de Chart.js résout ce problème, postez-le ici. Je me demande si destroy est cassé ou si nous ne l'utilisons pas correctement.
TheLettuceMaster
2
Agréable! Merci! Je viens d'ajouter $ ('# results-graph'). Remove (); $ ('# graph-container'). append ('<canvas id = "results-graph"> <canvas>'); avant la création du graphique.
Ignacio
.destroy () devrait fonctionner correctement. Si ce n'est pas le cas, après avoir appelé .destroy () pour dessiner un nouveau graphique, utilisez setTimeout ()
Sumeet Kale
c'est la seule solution qui a fonctionné pour moi, merci beaucoup, mais pour la largeur et la hauteur si vous les avez déjà réglées, vous devez les réinitialiser à la même valeur dans la fonction de réinitialisation
Sandy Elkassar
2
destroy () a échoué pour moi avec chartjs 2.8.0 mais votre solution a fonctionné! Dans mon cas, je n'ai utilisé $('#results-graph').remove(); $('#graph-container').append('<canvas id="results-graph"><canvas>');qu'avant lenew Chart(document.getElementById("myCanvas")
mimi
40

J'ai été confronté au même problème il y a quelques heures.

La méthode ".clear ()" efface réellement la toile, mais (évidemment) elle laisse l'objet vivant 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 ceci pour détruire toutes les instances de graphique créées. Cela nettoiera toutes les références stockées à l'objet de graphique dans Chart.js, ainsi que tous les écouteurs d'événements associés attachés par Chart.js."

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

Roberto Pierpaoli
la source
Pouvez-vous montrer un exemple? J'ai essayé d'utiliser le blocage plusieurs fois et cela ne fonctionne jamais. Je reçois toujours une erreur indiquant que la méthode n'existe pas.
Ben Hoffman
3
(<ChartInstance> this.chart) .destroy ();
David Dal Busco
2
C'est la bonne réponse. Pour de futures références, voir: stackoverflow.com/questions/40056555/…
ThePhi
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});
}
xchiltonx
la source
1
c'est la meilleure alternative
RafaSashi
Bon. Merci
Manjunath Siddappa
11

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");
Eric
la source
9

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 de la manière suivante:

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.

Javier Muñoz
la source
5

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 à 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 le canevas ne soit réutilisé pour un nouveau graphique.

Nicolas Macharia
la source
Cela fonctionne correctement pour moi, il semble que cela détruit les rappels de survol. Des chars tellement !!
Antoine Pointeau
4

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

var myChart = new Chart(ctx, data);
myChart.config.data = new_data;
myChart.update();
Sam G
la source
Je suis d'accord avec cela comme étant une bien meilleure solution - Destroy est extrêmement radical, alors que tout ce que nous voulons vraiment, c'est simplement redémarrer les "données".
TS
1

En utilisant CanvasJS, cela fonctionne pour moi, effacer le graphique et tout le reste, cela pourrait également fonctionner pour vous, vous permettant de configurer complètement votre canevas / graphique avant chaque traitement ailleurs:

var myDiv= document.getElementById("my_chart_container{0}";
myDiv.innerHTML = "";
aggaton
la source
pour moi, aucune des méthodes ci-dessus n'a fonctionné. Cela a parfaitement fonctionné. Merci beaucoup.
débutant le
1

Je n'ai pas pu faire fonctionner .destroy () non plus, c'est ce que je fais. Le div chart_parent est l'endroit où je veux que le canevas apparaisse. J'ai besoin de redimensionner la toile à 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>');
Chris
la source
1

Lorsque vous créez un nouveau canevas chart.js, cela génère un nouvel iframe caché, 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

zebus3d
la source
1

Cela a fonctionné pour moi. Ajoutez 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;
}`
Geai
la source
1

Si vous utilisez chart.js dans un projet Angular avec Typescript, vous pouvez essayer ce qui suit;

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>
Pulak Kanti Bhattacharyya
la source
1

Ce que nous avons fait est, avant l'initialisation du nouveau graphique, de supprimer / détruire l'instance de graphique des aperçus, si elle existe déjà, puis de 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.

Qammar Feroz
la source
1

Compléter la réponse d'Adam

Avec Vanilla 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

Gato de Schrödinger
la source
1

Modification simple pour 2020:

Cela a fonctionné pour moi. Changer le graphique en global en le rendant propriétaire de la fenêtre (changer la déclaration de var myChartà window myChart)

Vérifiez si la variable de graphique est déjà initialisée en tant que graphique, si c'est le cas, détruisez-la et créez-en une nouvelle, même si vous pouvez en créer une autre sur le même nom. Voici le code:

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

Esperons que ça marche!

Surya
la source
1
Merci beaucoup. Cela fonctionne pour moi.
Dante
0

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

Tremblante
la source
0

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é le .destroy().

Mais lors de la création du graphique, Chart.js écrit également la ._metapropriété dans la variable du jeu 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 nouvel ensemble de données ._metasans 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 l'ensemble de données après l'appel Chart.destroy().

Andrew Hudik
la source
0

Puisque détruire détruit en quelque sorte «tout», une solution simple et bon marché quand tout ce que vous voulez vraiment est de simplement «réinitialiser les données». La réinitialisation de vos ensembles de données dans 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 l'ensemble de votre graphique / ensemble de données et de tout reconstruire.

TS
la source
0

pour ceux qui comme moi utilisent une fonction pour créer plusieurs graphiques et veulent aussi mettre à jour un bloc, seule la fonction .destroy () a fonctionné pour moi, j'aurais aimé faire un .update (), qui semble plus propre mais .. . voici un extrait de code qui peut vous aider.

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 ...
SNS - Web et Informatique
la source