Wie lösche ich ein Diagramm von einer Leinwand, damit Hover-Ereignisse nicht ausgelöst werden können?

109

Ich verwende Chartjs, um ein Liniendiagramm anzuzeigen, und dies funktioniert einwandfrei:

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

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

Das Problem tritt jedoch auf, wenn ich versuche, die Daten für das Diagramm zu ändern. Ich aktualisiere das Diagramm, indem ich eine neue Instanz eines Diagramms mit den neuen Datenpunkten erstelle und so die Zeichenfläche neu initialisiere.

Das funktioniert gut. Wenn ich jedoch mit der Maus über das neue Diagramm schwebe und über bestimmte Positionen gehe, die den auf dem alten Diagramm angezeigten Punkten entsprechen, wird der Schwebeflug / die Beschriftung weiterhin ausgelöst und plötzlich ist das alte Diagramm sichtbar. Es bleibt sichtbar, während sich meine Maus an dieser Stelle befindet, und verschwindet, wenn Sie diesen Punkt verlassen. Ich möchte nicht, dass das alte Diagramm angezeigt wird. Ich möchte es komplett entfernen.

Ich habe versucht, sowohl die Leinwand als auch das vorhandene Diagramm zu löschen, bevor ich das neue lade. Mögen:

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

und

chart.clear();

Aber keines davon hat bisher funktioniert. Irgendwelche Ideen, wie ich das verhindern kann?

Adam Jones
quelle
18
Alter, das ist genau das Problem, das ich habe. Die "destroy ()" - Methode funktioniert nicht und macht mich wütend.
Neaumusic
Könnte ich fragen, wie Sie Zugriff auf das Diagrammobjekt erhalten? Ich habe das gleiche Problem, ich erstelle ein Diagramm und dann muss ich es bei der Behandlung eines Schaltflächenklicks zerstören, aber es hat eine völlig andere Funktion und ich kann keine Möglichkeit finden, über die Zeichenfläche oder den Kontext auf das Diagrammobjekt zuzugreifen Objekte.
Matt Williams
Für dieses Problem ist ein Fehler aufgetreten. Sehen Sie ihn hier. github.com/jtblin/angular-chart.js/issues/187
MDT
Hatte dieses Problem. Lösung zum Erstellen / Neuerstellen von stackoverflow.com/a/51882403/1181367
Chris

Antworten:

142

Ich hatte große Probleme damit

Zuerst habe ich es versucht, .clear()dann habe ich es versucht .destroy()und ich habe versucht, meine Diagrammreferenz auf null zu setzen

Was das Problem für mich endgültig behoben hat: Löschen des <canvas>Elements und erneutes Anhängen eines neuen Elements <canvas>an den übergeordneten Container


Mein spezifischer Code (offensichtlich gibt es dafür eine Million Möglichkeiten):

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
quelle
2
Arbeitete wie ein Champion. Wenn jemand weiß, ob Chart.js Version 2 dies behebt, posten Sie es hier. Ich frage mich, ob die Zerstörung kaputt ist oder ob wir sie falsch verwenden.
TheLettuceMaster
2
Nett! Vielen Dank! Ich habe gerade $ ('# results-graph') hinzugefügt. Remove (); $ ('# graph-container'). append ('<canvas id = "results-graph"> <canvas>'); vor der Diagrammerstellung.
Ignacio
.destroy () sollte gut funktionieren. Wenn dies nicht der Fall ist, verwenden Sie nach dem Aufruf von .destroy () zum Zeichnen eines neuen Diagramms setTimeout ()
Sumeet Kale
Das ist die einzige Lösung, die für mich funktioniert hat. Vielen Dank, aber für die Breite und Höhe, wenn Sie sie bereits fest eingestellt haben, sollten Sie sie in der Rücksetzfunktion auf den gleichen Wert zurücksetzen
Sandy Elkassar
2
destroy () ist für mich mit chartjs 2.8.0 fehlgeschlagen, aber Ihre Lösung hat einfach funktioniert! In meinem Fall habe ich nur $('#results-graph').remove(); $('#graph-container').append('<canvas id="results-graph"><canvas>');vor demnew Chart(document.getElementById("myCanvas")
mimi
40

Ich habe vor einigen Stunden das gleiche Problem gehabt.

Die Methode ".clear ()" löscht tatsächlich die Leinwand, lässt das Objekt jedoch (offensichtlich) lebendig und reaktiv.

Beim sorgfältigen Lesen der offiziellen Dokumentation im Abschnitt "Erweiterte Verwendung" ist mir die Methode ".destroy ()" aufgefallen, die wie folgt beschrieben wird:

"Verwenden Sie diese Option, um alle erstellten Diagramminstanzen zu zerstören. Dadurch werden alle Verweise auf das Diagrammobjekt in Chart.js sowie alle von Chart.js angehängten zugehörigen Ereignis-Listener bereinigt."

Es macht tatsächlich das, was es behauptet und es hat gut für mich funktioniert. Ich schlage vor, dass Sie es versuchen.

Roberto Pierpaoli
quelle
Könnten Sie ein Beispiel zeigen? Ich habe mehrmals versucht, das Blockieren zu verwenden, und es funktioniert nie. Ich erhalte immer eine Fehlermeldung, dass die Methode nicht existiert.
Ben Hoffman
3
(<ChartInstance> this.chart) .destroy ();
David Dal Busco
2
Das ist die richtige Antwort. Für zukünftige Referenzen siehe: 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
quelle
1
Dies ist die beste Alternative
RafaSashi
Gut. Danke
Manjunath Siddappa
11

Dies ist das einzige, was für mich funktioniert hat:

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

Ich hatte hier das gleiche Problem ... Ich habe versucht, die Methode destroy () und clear () zu verwenden, aber ohne Erfolg.

Ich habe es auf die nächste Weise gelöst:

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

Es funktioniert perfekt für mich ... Ich hoffe, dass es hilft.

Javier Muñoz
quelle
5

Das hat bei mir sehr gut funktioniert

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

Verwenden Sie .destroy , um alle erstellten Diagramminstanzen zu zerstören. Dadurch werden alle Verweise auf das Diagrammobjekt in Chart.js sowie alle zugehörigen Ereignis-Listener bereinigt, die von Chart.js angehängt werden. Dies muss aufgerufen werden, bevor die Zeichenfläche für ein neues Diagramm wiederverwendet wird.

Nicholas Macharia
quelle
Auf diese Weise funktioniert es für mich richtig, es sieht so aus, als würde es die Schweberückrufe zerstören. Panzer so sehr !!
Antoine Pointeau
4

Wir können die Diagrammdaten in Chart.js V2.0 wie folgt aktualisieren:

var myChart = new Chart(ctx, data);
myChart.config.data = new_data;
myChart.update();
Sam G.
quelle
Ich stimme dem als viel bessere Lösung zu - Destroy ist viel zu radikal, wenn wir wirklich nur die "Daten" neu starten wollen.
TS
1

Mit CanvasJS funktioniert dies für mich, wenn ich Diagramme lösche, und alles andere funktioniert möglicherweise auch für Sie, sodass Sie Ihre Zeichenfläche / Ihr Diagramm vor jeder Verarbeitung an anderer Stelle vollständig einrichten können:

var myDiv= document.getElementById("my_chart_container{0}";
myDiv.innerHTML = "";
Aggaton
quelle
Bei mir hat keine der oben genannten Methoden funktioniert. Das hat perfekt funktioniert. Vielen Dank.
Anfänger
1

Ich konnte .destroy () auch nicht zum Arbeiten bringen, also mache ich das so. In der Datei chart_parent div soll die Zeichenfläche angezeigt werden. Ich brauche die Größe der Leinwand jedes Mal, daher ist diese Antwort eine Erweiterung der obigen.

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
quelle
1

Wenn Sie eine neue chart.js-Zeichenfläche erstellen, wird ein neuer versteckter Iframe generiert. Sie müssen die Zeichenfläche und die alten iframes löschen.

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

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

zebus3d
quelle
1

Das hat bei mir funktioniert. Fügen Sie clearChart oben in Ihrem updateChart () einen Aufruf hinzu.

`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;
}`
Jay
quelle
1

Wenn Sie chart.js in einem Angular-Projekt mit Typescript verwenden, können Sie Folgendes versuchen:

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
quelle
1

Was wir getan haben, ist, vor der Initialisierung eines neuen Diagramms die Vorschau-Diagramminstanz zu entfernen / zu zerstören, falls bereits vorhanden, und dann beispielsweise ein neues Diagramm zu erstellen

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

Hoffe das hilft.

Qammar Feroz
quelle
1

Adams Antwort ergänzen

Mit 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
quelle
1

Einfache Bearbeitung für 2020:

Das hat bei mir funktioniert. Ändern Sie das Diagramm in global, indem Sie es als Fenster-Eigentümer festlegen (Ändern Sie die Deklaration von var myChartin window myChart).

Überprüfen Sie, ob die Diagrammvariable bereits als Diagramm initialisiert ist. Wenn ja, zerstören Sie sie und erstellen Sie eine neue. Sie können auch eine andere mit demselben Namen erstellen. Unten ist der Code:

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

Hoffe, es funktioniert!

Surya
quelle
1
Vielen Dank. Das funktioniert bei mir.
Dante
0

Bei mir hat das geklappt:

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

Scrapie
quelle
0

Chart.js hat einen Fehler: Chart.controller(instance)Registriert jedes neue Diagramm in einer globalen Eigenschaft Chart.instances[]und löscht es aus dieser Eigenschaft am .destroy().

Bei der Diagrammerstellung schreibt Chart.js jedoch auch ._metaEigenschaften in die Dataset-Variable:

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

und es löscht diese Eigenschaft nicht auf destroy().

Wenn Sie Ihr altes Dataset-Objekt verwenden, ohne es zu entfernen ._meta property, fügt Chart.js ein neues Dataset hinzu, ._metaohne vorherige Daten zu löschen . Somit sammelt Ihr Datensatzobjekt bei der Neuinitialisierung jedes Diagramms alle vorherigen Daten.

Um dies zu vermeiden, zerstören Sie das Dataset-Objekt nach dem Aufruf Chart.destroy().

Andrew Hudik
quelle
0

Da "zerstören" "alles" zerstört, ist eine billige und einfache Lösung, wenn Sie wirklich nur "die Daten zurücksetzen" möchten. Das Zurücksetzen Ihrer Datensätze auf ein leeres Array funktioniert ebenfalls einwandfrei. Wenn Sie also einen Datensatz mit Beschriftungen und einer Achse auf jeder Seite haben:

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

Danach können Sie einfach anrufen:

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

oder, je nachdem, ob Sie einen 2D-Datensatz verwenden:

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

Es ist viel leichter, als Ihr gesamtes Diagramm / Ihren gesamten Datensatz vollständig zu zerstören und alles neu zu erstellen.

TS
quelle
0

Für diejenigen, die wie ich eine Funktion verwenden, um mehrere Grafiken zu erstellen und sie auch einen Block zu aktualisieren, nur die Funktion .destroy () hat für mich funktioniert, hätte ich gerne eine .update () erstellt, die sauberer erscheint, aber .. Hier ist ein Code-Snippet, das helfen kann.

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
quelle