¿Cómo borrar un gráfico de un lienzo para que los eventos de desplazamiento no se puedan activar?

109

Estoy usando Chartjs para mostrar un gráfico de líneas y esto funciona bien:

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

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

Pero el problema ocurre cuando trato de cambiar los datos del gráfico. Actualizo el gráfico creando una nueva instancia de un gráfico con los nuevos puntos de datos y, por lo tanto, reinicializo el lienzo.

Esto funciona bien. Sin embargo, cuando coloco el cursor sobre el nuevo gráfico, si paso por encima de ubicaciones específicas correspondientes a los puntos que se muestran en el gráfico anterior, el cursor / etiqueta todavía se activa y, de repente, el gráfico anterior es visible. Permanece visible mientras mi mouse está en esta ubicación y desaparece cuando me muevo de ese punto. No quiero que se muestre el gráfico antiguo. Quiero eliminarlo por completo.

Intenté borrar tanto el lienzo como el gráfico existente antes de cargar el nuevo. Me gusta:

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

y

chart.clear();

Pero ninguno de estos ha funcionado hasta ahora. ¿Alguna idea sobre cómo puedo evitar que esto suceda?

Adam Jones
fuente
18
Amigo, este es exactamente el problema que tengo. El método "destroy ()" no funciona y me está cabreando.
neaumusic
¿Puedo preguntar cómo está obteniendo acceso al objeto gráfico? Tengo el mismo problema, creo un gráfico y luego, al manejar un botón, necesito destruirlo, pero tiene una función completamente diferente y no puedo encontrar una manera de acceder al objeto del gráfico a través del lienzo o el contexto. objetos.
Matt Williams
Hay un error abierto para este problema, véalo aquí. github.com/jtblin/angular-chart.js/issues/187
MDT
Tuve este problema. Solución para crear / recrear stackoverflow.com/a/51882403/1181367
Chris

Respuestas:

142

Tuve grandes problemas con esto

Primero lo intenté, .clear()luego lo intenté .destroy()e intenté establecer la referencia de mi gráfico en nulo

Lo que finalmente solucionó el problema para mí: eliminar el <canvas>elemento y luego volver a agregar uno nuevo <canvas>al contenedor principal


Mi código específico (obviamente hay un millón de formas de hacer esto):

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
fuente
2
Trabajó como un campeón. Si alguien sabe si Chart.js versión 2 soluciona esto, publíquelo aquí. Me pregunto si destruir está roto o si lo estamos usando incorrectamente.
TheLettuceMaster
2
¡Agradable! ¡Gracias! Acabo de agregar $ ('# results-graph'). Remove (); $ ('# graph-container'). append ('<canvas id = "results-graph"> <canvas>'); antes de la creación del gráfico.
Ignacio
.destroy () debería funcionar bien. Si no es así, después de llamar a .destroy () para dibujar un nuevo gráfico, use setTimeout ()
Sumeet Kale
Esa es la única solución que funcionó para mí, muchas gracias, pero para el ancho y la altura, si ya los fijaste, debes restablecerlos al mismo valor en la función de reinicio
Sandy Elkassar
2
destruir () me falló con chartjs 2.8.0 pero su solución simplemente funcionó! En mi caso, solo usé $('#results-graph').remove(); $('#graph-container').append('<canvas id="results-graph"><canvas>');antes delnew Chart(document.getElementById("myCanvas")
mimi
40

Me he enfrentado al mismo problema hace unas horas.

El método ".clear ()" en realidad borra el lienzo, pero (evidentemente) deja el objeto vivo y reactivo.

Leyendo detenidamente la documentación oficial , en la sección "Uso avanzado", he notado el método ".destroy ()", descrito a continuación:

"Use esto para destruir cualquier instancia de gráfico que se cree. Esto limpiará cualquier referencia almacenada al objeto de gráfico dentro de Chart.js, junto con cualquier detector de eventos asociado adjunto por Chart.js".

De hecho, hace lo que dice y me ha funcionado bien, te sugiero que lo pruebes.

Roberto Pierpaoli
fuente
¿Podría mostrarnos un ejemplo? He intentado usar el bloqueo varias veces y nunca funciona. Siempre recibo un error de que el método no existe.
Ben Hoffman
3
(<ChartInstance> this.chart) .destroy ();
David Dal Busco
2
Esta es la respuesta correcta. Para futuras referencias, consulte: 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
fuente
1
esta es la mejor alternativa
RafaSashi
Buena. Gracias
Manjunath Siddappa
11

Esto es lo único que funcionó para mí:

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

Tuve el mismo problema aquí ... Traté de usar el método destroy () y clear (), pero sin éxito.

Lo resolví de la siguiente manera:

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

Funciona perfecto para mí ... Espero que ayude.

Javier Muñoz
fuente
5

Esto funcionó muy bien para mi

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

Use .destroy this para destruir cualquier instancia de gráfico que se cree. Esto limpiará cualquier referencia almacenada al objeto de gráfico dentro de Chart.js, junto con cualquier detector de eventos asociado adjunto por Chart.js. Esto se debe llamar antes de que el lienzo se reutilice para un nuevo gráfico.

Nicolás Macharia
fuente
De esta manera funciona correctamente para mí, parece que destruye las devoluciones de llamada flotantes. ¡¡Tanques tanto !!
Antoine Pointeau
4

Podemos actualizar los datos del gráfico en Chart.js V2.0 de la siguiente manera:

var myChart = new Chart(ctx, data);
myChart.config.data = new_data;
myChart.update();
Sam G
fuente
Estoy de acuerdo con esto como una solución mucho mejor: Destroy es demasiado radical, cuando todo lo que realmente queremos es simplemente reiniciar los "datos".
TS
1

Al usar CanvasJS, esto me funciona al borrar el gráfico y todo lo demás, también podría funcionar para usted, ya que le permite configurar su lienzo / gráfico completamente antes de cada procesamiento en otro lugar:

var myDiv= document.getElementById("my_chart_container{0}";
myDiv.innerHTML = "";
aggatón
fuente
para mí ninguno de los métodos anteriores funcionó. Esto funcionó perfectamente. Muchas gracias.
principiante
1

Tampoco pude hacer que .destroy () funcione, así que esto es lo que estoy haciendo. El div chart_parent es donde quiero que aparezca el lienzo. Necesito que el lienzo cambie de tamaño cada vez, por lo que esta respuesta es una extensión de la anterior.

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

Cuando crea un nuevo lienzo de chart.js, esto genera un nuevo iframe oculto, necesita eliminar el lienzo y los viejos 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 });

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

zebus3d
fuente
1

Esto funcionó para mí. Agregue una llamada a clearChart, en la parte superior de su 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;
}`
Arrendajo
fuente
1

Si está utilizando chart.js en un proyecto Angular con Typescript, puede probar lo siguiente;

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

Lo que hicimos fue, antes de la inicialización de un nuevo gráfico, eliminar / destruir las vistas previas de la instancia del Gráfico, si ya existe, luego crear un nuevo gráfico, por ejemplo

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

Espero que esto ayude.

Qammar Feroz
fuente
1

Complementando la respuesta de Adam

Con 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
fuente
1

Edición simple para 2020:

Esto funcionó para mí. Cambie el gráfico a global haciéndolo propiedad de la ventana (cambie la declaración de var myCharta window myChart)

Compruebe si la variable del gráfico ya está inicializada como Gráfico, de ser así, destrúyala y cree una nueva, incluso puede crear otra con el mismo nombre. A continuación se muestra el código:

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

¡Espero que funcione!

Surya
fuente
1
Muchas gracias. Esto funciona para mi.
Dante
0

Para mí esto funcionó:

		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
fuente
0

Chart.js tiene un error: Chart.controller(instance)registra cualquier gráfico nuevo en una propiedad global Chart.instances[]y lo elimina de esta propiedad en .destroy().

Pero en la creación del gráfico, Chart.js también escribe la ._metapropiedad en la variable del conjunto de datos:

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

y no elimina esta propiedad en destroy().

Si usa su antiguo objeto de conjunto de datos sin eliminarlo ._meta property, Chart.js agregará un nuevo conjunto de datos ._metasin eliminar los datos anteriores. Por lo tanto, en la reinicialización de cada gráfico, su objeto de conjunto de datos acumula todos los datos anteriores.

Para evitar esto, destruya el objeto del conjunto de datos después de llamar Chart.destroy().

Andrew Hudik
fuente
0

Dado que destruir destruye "todo", una solución barata y simple cuando todo lo que realmente quieres es simplemente "restablecer los datos". Restablecer sus conjuntos de datos a una matriz vacía también funcionará perfectamente. Entonces, si tiene un conjunto de datos con etiquetas y un eje en cada lado:

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

Después de esto, simplemente puede llamar:

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

o, dependiendo de si está utilizando un conjunto de datos 2d:

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

Será mucho más liviano que destruir completamente todo su gráfico / conjunto de datos y reconstruir todo.

TS
fuente
0

para aquellos que como yo usan una función para crear varios gráficos y quieren actualizarlos también en un bloque, solo la función .destroy () funcionó para mí, me hubiera gustado hacer un .update (), que parece más limpio pero .. .Aquí hay un fragmento de código que puede ayudar.

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
fuente