如何清除一个图表从画布,使悬停事件不能被触发?

我使用 Chartjs 来显示一个线性图表,这个工作得很好:

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


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

但是当我试图更改图表的数据时,问题就出现了。我通过使用新的数据点创建一个 Chart 的新实例来更新图表,从而重新初始化画布。

这样挺好的。然而,当我将鼠标悬停在新图表上时,如果我碰巧浏览了与旧图表上显示的点相对应的特定位置,那么鼠标悬停/标签仍然会被触发,突然之间,旧图表就可以看到了。它保持可见,而我的鼠标在这个位置和消失时,移动了该点。我不想显示旧的图表。我想把它彻底移除。

我尝试在加载新图表之前清除画布和现有图表,比如:

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

还有

chart.clear();

但是到目前为止这些都没有效果。有什么办法可以阻止这种情况发生吗?

182034 次浏览

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

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

仔细阅读 官方文件,在“高级用法”部分,我注意到了方法“ . delete ()”,描述如下:

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

它确实做到了它所声称的,而且对我来说效果很好,我建议你试一试。

我对这个有很大的问题

首先我尝试 .clear(),然后我尝试 .destroy(),我试图设置我的图表参考为空

最终为我解决了这个问题: 删除 <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);
};
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});
}

我在这里遇到了同样的问题... ... 我尝试使用 delete ()和 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);

对我来说很有效... 我希望能有所帮助。

这是唯一对我有效的方法:

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

使用 CanvasJS,这对我清除图表和其他所有东西都有用,可能对您也有用,允许您在每次处理其他地方之前完全设置您的画布/图表:

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

对我来说,这个方法奏效了:

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

我不能。摧毁()工作,所以这是我正在做什么。我希望画布显示在 chart _ father div 中。我需要画布的大小调整每一次,所以这个答案是一个扩展上述之一。

HTML:

< div class = “ main _ section”> < div id = “ chart _ father”>

< div id = “ Legend”>

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

当您创建一个新的 chart.js 画布时,这将生成一个隐藏的新 iframe,您需要删除画布和旧的 iframe。

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

参考文献: Https://github.com/zebus3d/javascript/blob/master/chartjs_filtering_with_checkboxs.html

这招对我很管用

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

使用 。摧毁可以销毁所创建的任何图表实例。这将清除 Chart.js 中存储到图表对象的所有引用,以及 Chart.js 附加的所有相关事件侦听器。在重用画布创建新图表之前,必须调用这个函数。

Chart.js 有一个 bug: Chart.controller(instance)在全局属性 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()之后销毁数据集对象。

我们可以在 Chart.js V2.0中更新图表数据如下:

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

这招对我很管用。 在 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;
}`

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

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

或者,取决于你是否使用二维数据集:

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

它比完全摧毁整个图表/数据集和重新构建所有东西要轻量级得多。

如果您正在使用 chart.js 在一个 Angular 项目与类型,您可以尝试以下内容;

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>

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

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

希望这个能帮上忙。

对于那些谁喜欢我使用一个函数来创建几个图形,并希望更新他们一块也,只有功能。销毁()为我工作,我本来想做一个。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 ...

补充亚当的回答

与香草 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

2020年的简单编辑:

这招对我很管用。将图表更改为全局,使其为窗口所有(将声明从 var myChart更改为 window myChart)

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

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

希望能成功!

首先把图表在一些变量,然后历史它下一次在 init 之前

# 检查 myChart 对象是否存在,然后扭曲它

    if($scope.myChart) {
$scope.myChart.destroy();
}


$scope.myChart  = new Chart(targetCanvas

您应该将图表保存为一个变量。 在全局作用域上,如果它的纯 javascript,或者作为类属性,如果它的 Angular。

然后您就可以使用这个引用来调用 delete ()。

纯 Javascript:

var chart;


function startChart() {
// Code for chart initialization
chart = new Chart(...); // Replace ... with your chart parameters
}


function destroyChart() {
chart.destroy();
}

角度:

export class MyComponent {
chart;


constructor() {
// Your constructor code goes here
}


ngOnInit() {
// Probably you'll start your chart here


// Code for chart initialization
this.chart = new Chart(...); // Replace ... with your chart parameters
}


destroyChart() {
this.chart.destroy();
}
}

在创建图表之前只需声明 let doughnut = null

const doughnutDriverStatsChartCanvas = $('#dougnautChartDriverStats').get(0).getContext('2d')
const doughnutOptionsDriverStats = {
maintainAspectRatio: false,
responsive: true,
}
let doughnut = null
doughnut = new Chart(doughnutDriverStatsChartCanvas, {
type: 'doughnut',
data: doughnutChartDriverStats,
options: doughnutOptionsDriverStats
})

最好使用 Chart.JS 特定的功能,首先检查现有的图表实例,然后执行 摧毁或清除,以便重用相同的画布元素来呈现另一个图表,而不是从 JS 内部处理 HTML 元素。

ChartJs 的 < strong > getChart (key) -从给定的键查找图表实例。

  • 如果键是字符串,则将其解释为 Chart 的 Canvas 元素的 ID。
  • 键也可以是 CanvasRenderingContext2D 或 HTMLDOMElement。

注意: 如果没有找到图表,这将返回 未定义。如果找到该图表的实例,则表示该图表必须先前已创建。

// JS - Destroy exiting Chart Instance to reuse <canvas> element
let chartStatus = Chart.getChart("myChart"); // <canvas> id
if (chartStatus != undefined) {
chartStatus.destroy();
//(or)
// chartStatus.clear();
}
//-- End of chart destroy


var chartCanvas = $('#myChart'); //<canvas> id
chartInstance = new Chart(chartCanvas, {
type: 'line',
data: data
});
<!-- HTML -Line Graph - Chart.js -->
<div class="container-fluid" id="chartContainer">
<canvas id="myChart" width="400" height="150">   </canvas>
</div>

这种方法可以避免从 JS 内部将 Canvas 元素移除-创建-附加到 DIV 中。