Làm cách nào để xóa biểu đồ khỏi canvas để không thể kích hoạt các sự kiện di chuột?


109

Tôi đang sử dụng Chartjs để hiển thị Biểu đồ đường và điều này hoạt động tốt:

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

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

Nhưng sự cố xảy ra khi tôi cố gắng thay đổi dữ liệu cho Biểu đồ. Tôi cập nhật biểu đồ bằng cách tạo một phiên bản Biểu đồ mới với các điểm dữ liệu mới và do đó khởi động lại khung vẽ.

Điều này hoạt động tốt. Tuy nhiên, khi tôi di chuột qua biểu đồ mới, nếu tôi tình cờ đi qua các vị trí cụ thể tương ứng với các điểm hiển thị trên biểu đồ cũ, di chuột / nhãn vẫn được kích hoạt và đột nhiên biểu đồ cũ hiển thị. Nó vẫn hiển thị khi chuột của tôi ở vị trí này và biến mất khi di chuyển khỏi điểm đó. Tôi không muốn biểu đồ cũ hiển thị. Tôi muốn loại bỏ nó hoàn toàn.

Tôi đã cố gắng xóa cả canvas và biểu đồ hiện có trước khi tải biểu đồ mới. Giống:

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

chart.clear();

Nhưng không ai trong số này đã hoạt động cho đến nay. Bất kỳ ý tưởng nào về cách tôi có thể ngăn điều này xảy ra?


18
Anh bạn, đây chính xác là vấn đề tôi đang gặp phải. Phương thức "hủy diệt ()" không hoạt động và nó làm tôi bực mình.
neaumusic

Tôi có thể hỏi làm thế nào bạn có được quyền truy cập vào đối tượng biểu đồ? Tôi đang gặp phải vấn đề tương tự, tôi tạo một biểu đồ và sau đó khi xử lý một lần nhấp vào nút, tôi cần phải hủy nó đi, nhưng nó ở một chức năng hoàn toàn khác và tôi không thể tìm thấy cách truy cập đối tượng biểu đồ thông qua canvas hoặc ngữ cảnh các đối tượng.
Matt Williams

Có một lỗi đã được mở cho vấn đề này, hãy xem nó ở đây. github.com/jtblin/angular-chart.js/issues/187
MDT

Có vấn đề này. Giải pháp tạo / tạo lại stackoverflow.com/a/51882403/1181367
Chris

Câu trả lời:


142

Tôi đã gặp vấn đề lớn với điều này

Đầu tiên tôi đã thử .clear()sau đó tôi đã thử .destroy()và tôi đã thử đặt tham chiếu biểu đồ của mình thành null

Điều gì cuối cùng đã khắc phục sự cố cho tôi: xóa <canvas>phần tử và sau đó xuất hiện lại một phần tử mới <canvas>vào vùng chứa mẹ


Mã cụ thể của tôi (rõ ràng là có hàng triệu cách để làm điều này):

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
Làm việc như một nhà vô địch. Nếu ai biết liệu Chart.js phiên bản 2 có sửa lỗi này không, hãy đăng nó ở đây. Tôi tự hỏi liệu tiêu diệt có bị hỏng hay chúng tôi đang sử dụng nó không đúng cách.
TheLet MobileMaster

2
Đẹp! Cảm ơn! Tôi vừa thêm $ ('# results-graph'). Remove (); $ ('# graph-container'). append ('<canvas id = "results-graph"> <canvas>'); trước khi tạo biểu đồ.
Ignacio

.destroy () sẽ hoạt động tốt. Nếu không, sau khi gọi .destroy () để vẽ biểu đồ mới, hãy sử dụng setTimeout ()
Sumeet Kale

đó là giải pháp duy nhất làm việc cho tôi cảm ơn rất nhiều, nhưng đối với chiều rộng và chiều cao nếu bạn đã cài đặt chúng cố định, bạn nên thiết lập lại chúng với giá trị tương tự trong hàm reset
Sandy Elkassar

2
hủy () không thành công đối với tôi với chartjs 2.8.0 nhưng giải pháp của bạn chỉ hoạt động! Trong trường hợp của tôi, tôi chỉ sử dụng $('#results-graph').remove(); $('#graph-container').append('<canvas id="results-graph"><canvas>');trướcnew Chart(document.getElementById("myCanvas")
mimi

40

Tôi đã phải đối mặt với cùng một vấn đề cách đây vài giờ.

Phương thức ".clear ()" thực sự xóa canvas, nhưng (hiển nhiên) nó để lại đối tượng sống và phản ứng.

Đọc kỹ tài liệu chính thức , trong phần "Cách sử dụng nâng cao", tôi nhận thấy phương thức ".destroy ()", được mô tả như sau:

"Sử dụng điều này để hủy mọi trường hợp biểu đồ được tạo. Thao tác này sẽ xóa mọi tham chiếu được lưu trữ tới đối tượng biểu đồ trong Chart.js, cùng với mọi trình nghe sự kiện liên quan được Chart.js đính kèm."

Nó thực sự làm những gì nó tuyên bố và nó đã hoạt động tốt cho tôi, tôi khuyên bạn nên thử nó.


Bạn có thể cho một ví dụ? Tôi đã thử sử dụng tính năng chặn nhiều lần và nó không bao giờ hoạt động. Tôi luôn nhận được lỗi rằng phương pháp không tồn tại.
Ben Hoffman,

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

2
Đây là anszwer đúng. Đối với các tài liệu tham khảo trong tương lai, hãy xem: 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
đây là giải pháp thay thế tốt nhất
RafaSashi

Tốt. Cảm ơn
Manjunath Siddappa

11

Đây là điều duy nhất phù hợp với tôi:

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

9

Tôi đã gặp vấn đề tương tự ở đây ... Tôi đã cố gắng sử dụng phương thức hủy () và clear (), nhưng không thành công.

Tôi đã giải quyết nó theo cách tiếp theo:

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

Nó hoạt động hoàn hảo với tôi ... Tôi hy vọng rằng nó sẽ hữu ích.


5

Điều này làm việc rất tốt cho tôi

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

Sử dụng .destroy này để hủy mọi trường hợp biểu đồ được tạo. Thao tác này sẽ xóa mọi tham chiếu được lưu trữ đến đối tượng biểu đồ trong Chart.js, cùng với mọi trình nghe sự kiện liên quan được Chart.js đính kèm. Điều này phải được gọi trước khi canvas được sử dụng lại cho một biểu đồ mới.


Cách này phù hợp với tôi, có vẻ như nó sẽ phá hủy các lệnh gọi lại di chuột. Xe tăng rất nhiều !!
Antoine Pointeau

4

Chúng tôi có thể cập nhật dữ liệu biểu đồ trong Chart.js V2.0 như sau:

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

Tôi đồng ý rằng đây là một giải pháp tốt hơn nhiều - Destroy thực sự quá triệt để, khi tất cả những gì chúng ta thực sự muốn là chỉ khởi động lại "dữ liệu".
TS

1

Sử dụng CanvasJS, điều này phù hợp với tôi khi xóa biểu đồ và mọi thứ khác, cũng có thể hoạt động cho bạn, cho phép bạn thiết lập canvas / biểu đồ của mình đầy đủ trước mỗi lần xử lý ở nơi khác:

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

đối với tôi không có các phương pháp trên hoạt động. Điều này đã hoạt động hoàn hảo. Cảm ơn rất nhiều.
người mới bắt đầu

1

Tôi cũng không thể làm cho .destroy () hoạt động nên đây là những gì tôi đang làm. Div chart_parent là nơi tôi muốn canvas hiển thị. Tôi cần canvas để thay đổi kích thước mỗi lần, vì vậy câu trả lời này là phần mở rộng của câu trả lời ở trên.

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

Điều này đã làm việc cho tôi. Thêm lệnh gọi vào clearChart, ở trên cùng oF your 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;
}`

1

Nếu bạn đang sử dụng chart.js trong một dự án Angular với Typescript, bạn có thể thử những cách sau;

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

Những gì chúng tôi đã làm là, trước khi khởi tạo biểu đồ mới, hãy xóa / hủy bản xem trước Bản sao biểu đồ, nếu đã tồn tại, sau đó tạo một biểu đồ mới, ví dụ:

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

Hi vọng điêu nay co ich.


1

Bổ sung câu trả lời của Adam

Với 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

Chỉnh sửa đơn giản cho năm 2020:

Điều này đã làm việc cho tôi. Thay đổi biểu đồ thành toàn cục bằng cách làm cho nó sở hữu cửa sổ (Thay đổi khai báo từ var myChartthànhwindow myChart )

Kiểm tra xem biến biểu đồ đã được khởi tạo dưới dạng Biểu đồ chưa, nếu có, hãy phá hủy nó và tạo một biến mới, thậm chí bạn có thể tạo một biến khác có cùng tên. Dưới đây là mã:

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

Hy vọng nó hoạt động!


1
Cảm ơn rất nhiều. Điều này làm việc cho tôi.
Dante

0

Đối với tôi điều này đã hoạt động:

		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 có một lỗi: Chart.controller(instance)đăng ký bất kỳ biểu đồ mới nào trong thuộc tính toàn cục Chart.instances[]và xóa nó khỏi thuộc tính này vào ngày .destroy().

Nhưng khi tạo biểu đồ Chart.js cũng ghi thuộc ._metatính vào biến tập dữ liệu:

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

và nó không xóa thuộc tính này trên destroy().

Nếu bạn sử dụng đối tượng tập dữ liệu cũ của mình mà không xóa ._meta property, Chart.js sẽ thêm tập dữ liệu mới vào ._metamà không xóa dữ liệu trước đó. Do đó, tại mỗi lần khởi tạo lại biểu đồ, đối tượng tập dữ liệu của bạn sẽ tích lũy tất cả dữ liệu trước đó.

Để tránh điều này, hãy hủy đối tượng tập dữ liệu sau khi gọi Chart.destroy().


0

Vì loại hủy phá hủy "mọi thứ", một giải pháp rẻ và đơn giản khi tất cả những gì bạn thực sự muốn là chỉ cần "thiết lập lại dữ liệu". Đặt lại bộ dữ liệu của bạn thành một mảng trống cũng sẽ hoạt động hoàn toàn tốt. Vì vậy, nếu bạn có một tập dữ liệu với các nhãn và một trục ở mỗi bên:

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

Sau đó, bạn chỉ cần gọi:

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

hoặc, tùy thuộc vào việc bạn đang sử dụng tập dữ liệu 2d:

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

Nó sẽ nhẹ hơn rất nhiều so với việc phá hủy hoàn toàn toàn bộ biểu đồ / tập dữ liệu của bạn và xây dựng lại mọi thứ.


0

đối với những người thích tôi sử dụng một hàm để tạo một số đồ họa và cũng muốn cập nhật chúng một khối, chỉ có hàm .destroy () phù hợp với tôi, tôi muốn tạo .update (), có vẻ gọn gàng hơn nhưng .. . đây là một đoạn mã có thể hữu ích.

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 ...
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.