Bagaimana cara menghapus grafik dari kanvas sehingga acara hover tidak dapat dipicu?


109

Saya menggunakan Chartjs untuk menampilkan Diagram Garis dan ini berfungsi dengan baik:

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

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

Tetapi masalah terjadi ketika saya mencoba mengubah data untuk Bagan. Saya memperbarui grafik dengan membuat contoh baru dari Bagan dengan titik data baru, dan dengan demikian menginisialisasi ulang kanvas.

Ini bekerja dengan baik. Namun, ketika saya mengarahkan kursor ke grafik baru, jika saya kebetulan pergi ke lokasi tertentu yang sesuai dengan poin yang ditampilkan pada grafik lama, hover / label masih terpicu dan tiba-tiba grafik lama terlihat. Itu tetap terlihat saat mouse saya berada di lokasi ini dan menghilang saat berpindah dari titik itu. Saya tidak ingin grafik lama ditampilkan. Saya ingin menghapusnya sepenuhnya.

Saya sudah mencoba untuk menghapus kanvas dan bagan yang ada sebelum memuat yang baru. Suka:

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

dan

chart.clear();

Tapi sejauh ini tidak ada yang berhasil. Ada ide tentang bagaimana saya bisa menghentikan hal ini terjadi?


18
Sobat, inilah masalah yang saya alami. Metode "destroy ()" tidak berhasil dan membuatku kesal.
neaumusic

Bisakah saya bertanya bagaimana Anda mendapatkan akses ke objek bagan? Saya mengalami masalah yang sama, saya membuat bagan dan kemudian saat menangani klik tombol saya perlu menghancurkannya, tetapi fungsinya sama sekali berbeda dan saya tidak dapat menemukan cara untuk mengakses objek bagan melalui kanvas atau konteks benda.
Matt Williams

Ada bug yang dibuka untuk masalah ini, lihat di sini. github.com/jtblin/angular-chart.js/issues/187
MDT

Punya masalah ini. Solusi untuk membuat / membuat ulang stackoverflow.com/a/51882403/1181367
Chris

Jawaban:


143

Saya punya masalah besar dengan ini

Pertama saya mencoba .clear()kemudian saya mencoba .destroy()dan saya mencoba mengatur referensi grafik saya ke null

Apa yang akhirnya memperbaiki masalah saya: menghapus <canvas>elemen lalu menambahkan kembali yang baru <canvas>ke penampung induk


Kode spesifik saya (jelas ada jutaan cara untuk melakukan ini):

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
Bekerja seperti seorang juara. Jika ada yang tahu jika Chart.js versi 2 memperbaiki ini, posting di sini. Saya bertanya-tanya apakah perusakan rusak atau jika kita menggunakannya secara tidak benar.
TheLettuceMaster

2
Bagus! Terima kasih! Saya baru saja menambahkan $ ('# results-graph']. Remove (); $ ('# graph-container'). append ('<canvas id = "results-graph"> <canvas>'); sebelum pembuatan grafik.
Ignacio

.destroy () seharusnya berfungsi dengan baik. Jika tidak, setelah memanggil .destroy () untuk menggambar grafik baru, gunakan setTimeout ()
Sumeet Kale

itu satu-satunya solusi yang berhasil untuk saya banyak terima kasih, tetapi untuk lebar dan tinggi jika Anda sudah mengaturnya tetap, Anda harus mengatur ulang ke nilai yang sama dalam fungsi reset
Sandy Elkassar

2
destroy () gagal untuk saya dengan chartjs 2.8.0 tetapi solusi Anda berhasil! Dalam kasus saya, saya hanya menggunakan $('#results-graph').remove(); $('#graph-container').append('<canvas id="results-graph"><canvas>');sebelumnew Chart(document.getElementById("myCanvas")
mimi

40

Saya telah menghadapi masalah yang sama beberapa jam yang lalu.

Metode ".clear ()" sebenarnya membersihkan kanvas, tetapi (ternyata) membiarkan objek hidup dan reaktif.

Membaca dengan cermat dokumentasi resmi , di bagian "Penggunaan lanjutan", saya telah memperhatikan metode ".destroy ()", yang dijelaskan sebagai berikut:

"Gunakan ini untuk menghancurkan semua contoh bagan yang dibuat. Ini akan membersihkan semua referensi yang disimpan ke objek bagan dalam Chart.js, bersama dengan pendengar peristiwa terkait yang dilampirkan oleh Chart.js."

Ini benar-benar melakukan apa yang diklaimnya dan berfungsi dengan baik untuk saya, saya sarankan Anda untuk mencobanya.


Bisakah Anda menunjukkan contoh? Saya telah mencoba menggunakan pemblokiran beberapa kali dan tidak pernah berhasil. Saya selalu menerima pesan kesalahan bahwa metode ini tidak ada.
Ben Hoffman

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

2
Ini jawaban yang benar. Untuk referensi di masa mendatang, lihat: 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});
}

1
ini adalah alternatif terbaik
RafaSashi

Bagus. Terima kasih
Manjunath Siddappa

11

Ini adalah satu-satunya hal yang berhasil untuk saya:

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

9

Saya memiliki masalah yang sama di sini ... Saya mencoba menggunakan metode destroy () dan clear (), tetapi tidak berhasil.

Saya menyelesaikannya dengan cara berikutnya:

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

Ini bekerja sempurna untuk saya ... Saya harap Itu membantu.


5

Ini bekerja dengan sangat baik untuk saya

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

Gunakan .destroy this untuk menghancurkan semua instance grafik yang dibuat. Ini akan membersihkan semua referensi yang disimpan ke objek grafik dalam Chart.js, bersama dengan event listener terkait yang dilampirkan oleh Chart.js. Ini harus dipanggil sebelum kanvas digunakan kembali untuk grafik baru.


Cara ini berfungsi dengan baik untuk saya, sepertinya itu menghancurkan callback hover. Tanks sangat banyak !!
Antoine Pointeau

4

Kami dapat memperbarui data grafik di Chart.js V2.0 sebagai berikut:

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

Saya setuju dengan ini sebagai solusi yang jauh lebih baik - Hancurkan terlalu radikal, padahal yang kita inginkan hanyalah memulai ulang "data".
TS

1

Menggunakan CanvasJS, ini berfungsi untuk saya membersihkan bagan dan yang lainnya, mungkin bekerja untuk Anda juga, memungkinkan Anda mengatur kanvas / bagan Anda sepenuhnya sebelum setiap pemrosesan di tempat lain:

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

bagi saya non dari metode di atas berhasil. Ini bekerja dengan sempurna. Terima kasih banyak.
pemula

1

Saya juga tidak bisa membuat .destroy () berfungsi jadi inilah yang saya lakukan. Div chart_parent adalah tempat saya ingin kanvas muncul. Saya perlu kanvas untuk mengubah ukuran setiap kali, jadi jawaban ini merupakan perpanjangan dari yang di atas.

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

Ini berhasil untuk saya. Tambahkan panggilan ke clearChart, di bagian atas updateChart Anda ()

`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

Jika Anda menggunakan chart.js dalam proyek Angular dengan Typecript, Anda dapat mencoba yang berikut;

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

Yang kita lakukan adalah, sebelum inisialisasi chart baru, hapus / hancurkan instance Chart preview, jika sudah ada, lalu buat chart baru, misalnya

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

Semoga ini membantu.


1

Melengkapi Jawaban Adam

Dengan 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


1

Pengeditan sederhana untuk tahun 2020:

Ini berhasil untuk saya. Ubah grafik menjadi global dengan menjadikannya milik jendela (Ubah deklarasi dari var myChartmenjadiwindow myChart )

Periksa apakah variabel grafik sudah diinisialisasi sebagai Chart, jika demikian, hancurkan dan buat yang baru, bahkan Anda dapat membuat yang lain dengan nama yang sama. Berikut kodenya:

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

Semoga berhasil!


1
Terima kasih banyak. Ini berhasil untuk saya.
Dante

0

Bagi saya ini berhasil:

		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 memiliki bug: Chart.controller(instance)mendaftarkan bagan baru di properti global Chart.instances[]dan menghapusnya dari properti ini pada .destroy().

Tetapi pada pembuatan grafik, Chart.js juga menulis ._metaproperti ke variabel set data:

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

dan tidak menghapus properti ini di destroy().

Jika Anda menggunakan objek dataset lama Anda tanpa menghapus ._meta property, Chart.js akan menambahkan dataset baru ke._meta tanpa menghapus data sebelumnya. Jadi, pada setiap inisialisasi ulang diagram, objek set data Anda mengakumulasikan semua data sebelumnya.

Untuk menghindarinya, hancurkan objek set data setelah dipanggil Chart.destroy().


0

Karena jenis menghancurkan menghancurkan "segalanya", solusi yang murah dan sederhana ketika semua yang Anda inginkan hanyalah "mengatur ulang data". Mengatur ulang kumpulan data Anda ke array kosong juga akan berfungsi dengan baik. Jadi, jika Anda memiliki kumpulan data dengan label, dan sumbu di setiap sisinya:

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

Setelah ini, Anda cukup menelepon:

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

atau, tergantung apakah Anda menggunakan kumpulan data 2d:

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

Ini akan jauh lebih ringan daripada menghancurkan seluruh grafik / dataset Anda, dan membangun kembali semuanya.


0

bagi mereka yang menyukai saya menggunakan fungsi untuk membuat beberapa grafik dan ingin memperbaruinya juga, hanya fungsi .destroy () yang berfungsi untuk saya, saya ingin membuat .update (), yang terlihat lebih bersih tetapi .. Berikut adalah potongan kode yang mungkin membantu.

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 ...
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.