如何从画布上清除图表以使悬停事件无法触发?


109

我正在使用Chartjs显示折线图,并且可以正常工作:

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

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

但是,当我尝试更改图表数据时,会出现问题。我通过使用新的数据点创建图表的新实例来更新图形,然后重新初始化画布。

这很好。但是,当我将鼠标悬停在新图表上时,如果碰巧越过了与旧图表上显示的点相对应的特定位置,则仍会触发悬停/标签,并且突然可见旧图表。当我的鼠标位于该位置时,它仍然可见,而从该点移开时,它消失。我不希望显示旧图表。我想将其完全删除。

在加载新画布之前,我已尝试清除画布和现有图表。喜欢:

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

chart.clear();

但是到目前为止,这些方法都没有起作用。关于如何阻止这种情况的任何想法?


18
杜德,这正是我遇到的问题。“ destroy()”方法无效,这让我很生气。
neaumusic

请问您如何访问图表对象?我遇到了同样的问题,我创建了一个图表,然后在处理按钮时单击,需要销毁它,但是它的功能完全不同,无法找到通过画布或上下文访问图表对象的方法。对象。
马特·威廉姆斯

已为此问题打开一个错误,请在此处查看。github.com/jtblin/angular-chart.js/issues/187
MDT

有这个问题。创建/重新创建的解决方案 stackoverflow.com/a/51882403/1181367的
克里斯(Chris)

Answers:


142

我对此有很大的问题

首先我尝试了.clear()然后尝试了,.destroy()并且尝试将图表引用设置为null

最终为我解决了这个问题:删除<canvas>元素,然后将新元素重新添加<canvas>到父容器


我的特定代码(显然有百万种方法可以做到):

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
像冠军一样工作。如果有人知道Chart.js版本2是否可以解决此问题,请在此处发布。我想知道是否破坏销毁,或者我们使用不正确。
TheLettuceMaster 2015年

2
真好!谢谢!我刚刚添加了$('#results-graph')。remove(); $('#graph-container')。append('<canvas id =“ results-graph”> <canvas>'); 在创建图表之前。
伊格纳西奥(Ignacio)

.destroy()应该可以正常工作。如果没有,请在调用.destroy()绘制新图表后,使用setTimeout()
Sumeet Kale

这是唯一对我
有用的

2
由于chartjs 2.8.0,destroy()对我失败了,但是您的解决方案才起作用!就我而言,我只$('#results-graph').remove(); $('#graph-container').append('<canvas id="results-graph"><canvas>');new Chart(document.getElementById("myCanvas")
mimi

40

几个小时前我也遇到了同样的问题。

“ .clear()”方法实际上清除了画布,但是(显然)它使对象保持活动状态和反应性。

仔细阅读“高级用法”部分中的官方文档,我注意到方法“ .destroy()”,如下所述:

“使用它来销毁创建的任何图表实例。这将清除Chart.js中存储到Chart对象的所有引用以及Chart.js附加的任何相关事件侦听器。”

它实际上完成了它声称的功能,并且对我来说效果很好,我建议您尝试一下。


你能举个例子吗?我曾尝试多次使用阻止功能,但从未成功。我总是收到一个错误消息,指出该方法不存在。
本霍夫曼

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

2
这是正确的答案。有关将来的参考,请参阅: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
这是最好的选择
RafaSashi

好一个 谢谢
Manjunath Siddappa,

11

这是唯一对我有用的东西:

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

9

我在这里遇到了同样的问题...我尝试使用destroy()和clear()方法,但是没有成功。

我以另一种方式解决了它:

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

它对我来说很完美……我希望它能有所帮助。


5

这对我来说很好

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

使用.destroy this销毁创建的所有图表实例。这将清除Chart.js中存储到chart对象的所有引用,以及Chart.js附加的所有关联事件侦听器。必须在画布重新用于新图表之前调用此方法。


这种方式对我来说正常工作,好像它破坏了悬停回调。坦克太多了!
Antoine Pointeau,2013年

4

我们可以按以下方式更新Chart.js V2.0中的图表数据:

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

我同意这是一个更好的解决方案-当我们真正想要的只是重新启动“数据”时,销毁太过激进了。
TS

1

使用CanvasJS,这对我来说可以清除图表和其他所有内容,也可能对您有用,因为您可以在其他地方进行每次处理之前完全设置好画布/图表:

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

对我来说,以上方法都不奏效。这工作得很好。非常感谢。
初学者

1

我也无法使.destroy()工作,所以这就是我正在做的事情。chart_parent div是我要显示画布的位置。我每次都需要调整画布的大小,因此此答案是上述内容的扩展。

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

这对我有用。在updateChart()的顶部添加对clearChart的调用

`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

如果您在带有Typescript的Angular项目中使用chart.js,则可以尝试以下操作;

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

我们要做的是,在初始化新图表之前,删除/销毁预览Chart实例(如果已经存在),然后创建一个新图表,例如

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

希望这可以帮助。


1

补充亚当的答案

使用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

2020年的简单编辑:

这对我有用。通过使其成为窗口所有者来将图表更改为全局(将声明从更改var myChartwindow myChart

检查chart变量是否已经初始化为Chart,如果是,则销毁它并创建一个新变量,即使您可以使用相同的名称创建另一个变量。下面是代码:

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

希望它有效!


1
非常感谢。这对我有用。
但丁

0

对我来说,这工作:

		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有一个错误: Chart.controller(instance)在global属性中注册任何新图表,Chart.instances[]然后在上将其从该属性中删除.destroy()

但是在创建图表时,Chart.js还将._meta属性写入数据集变量:

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

并且不会删除上的此属性destroy()

如果您使用旧的数据集对象而不删除._meta property,则Chart.js将向其中添加新的数据集._meta而不删除以前的数据。因此,在每个图表重新初始化时,您的数据集对象都会累积所有先前的数据。

为了避免这种情况,请在调用后销毁数据集对象Chart.destroy()


0

由于销毁类型会销毁“一切”,因此,当您真正想要的只是一个“重置数据”时,一种廉价而简单的解决方案。将您的数据集重置为一个空数组也将很好地工作。因此,如果您的数据集带有标签,并且每侧都有一个轴:

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

之后,您可以简单地调用:

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

或者,取决于您是否使用2D数据集:

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

比完全销毁整个图表/数据集并重建所有内容,它要轻巧得多。


0

对于那些喜欢我的人,使用一个函数来创建多个图形,并且也想对它们进行更新,只有.destroy()函数对我有用,我想制作一个.update(),看上去更干净,但是..这是一个可能有用的代码段。

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 ...
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.