如何从画布上清除图表,使悬停事件无法触发
How to clear a chart from a canvas so that hover events cannot be triggered?
我正在使用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();
但是到目前为止,这些方法都没有奏效。有什么办法能阻止这一切发生吗?
我遇到了很大的问题
首先我尝试了.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);
};
几个小时前我也遇到过同样的问题。
".clear()"方法实际上清除了画布,但(显然)它使对象保持活动状态。
仔细阅读官方文档,在"高级用法"部分,我注意到方法".destroy()",描述如下:
"使用这个来销毁创建的任何图表实例。这将清理存储在chart .js中的任何对图表对象的引用,以及由Chart.js附加的任何相关事件侦听器。"
它确实做到了它所声称的,它对我来说工作得很好,我建议你试一试。
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});
}
这是我唯一有效的方法:
document.getElementById("chartContainer").innerHTML = ' ';
document.getElementById("chartContainer").innerHTML = '<canvas id="myCanvas"></canvas>';
var ctx = document.getElementById("myCanvas").getContext("2d");
我们可以在chart .js V2.0中更新图表数据:
var myChart = new Chart(ctx, data);
myChart.config.data = new_data;
myChart.update();
我在这里遇到了同样的问题…我尝试使用destroy()和clear()方法,但是没有成功。
我用另一种方法解决了它:
HTML:<div id="pieChartContent">
<canvas id="pieChart" width="300" height="300"></canvas>
</div>
Javascript: var pieChartContent = document.getElementById('pieChartContent');
pieChartContent.innerHTML = ' ';
$('#pieChartContent').append('<canvas id="pieChart" width="300" height="300"><canvas>');
ctx = $("#pieChart").get(0).getContext("2d");
var myPieChart = new Chart(ctx).Pie(data, options);
这对我来说是完美的…我希望这对你有帮助。
这工作对我来说很好
var ctx = $("#mycanvas");
var LineGraph = new Chart(ctx, {
type: 'line',
data: chartdata});
LineGraph.destroy();
使用.destroy this来销毁所有创建的图表实例。这将清除存储到chart .js中图表对象的任何引用,以及由chart .js附加的任何相关事件侦听器。这必须在画布被重新用于新图表之前调用。
最好使用chart . JS特定的功能来最初检查现有的图表实例,然后执行destroy或clear,以便重用相同的画布元素来呈现另一个图表,而不是从JS中处理HTML元素。
ChartJs的getChart(key) -从给定的键中查找图表实例。
- 如果键是字符串,它将被解释为图表的Canvas元素的ID。
- 键也可以是CanvasRenderingContext2D或HTMLDOMElement。
注意:如果没有找到图表,将返回undefined。如果找到图表的实例,则表示该图表必须先前已创建。
// 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。
简单编辑2020:
这对我有用。通过将图表设置为window owned,将其更改为global(将声明从var myChart
更改为window myChart
)
检查图表变量是否已经初始化为图表,如果是,销毁它并创建一个新的,即使你可以创建一个相同的名称。下面是代码:
if(window.myChart instanceof Chart)
{
window.myChart.destroy();
}
var ctx = document.getElementById('myChart').getContext("2d");
希望它能起作用!
补充亚当的回答
With 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
使用CanvasJS,这对我清理图表和其他一切都有效,也可能适用于您,授予您在其他地方的每次处理之前完全设置画布/图表:
var myDiv= document.getElementById("my_chart_container{0}";
myDiv.innerHTML = "";
我不能得到。destroy()工作,所以这就是我所做的。chart_parentdiv是画布显示的位置。我需要画布每次都调整大小,所以这个答案是上面那个的扩展。
HTML: <div class="main_section" >
<div id="chart_parent"></div>
<div id="legend"></div>
</div>
$('#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
这对我有效。在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;
}`
既然destroy破坏了"一切",那么当你真正想要的只是"重置数据"时,一个便宜而简单的解决方案。将数据集重置为空数组也可以很好地工作。所以,如果你有一个带有标签的数据集,每边都有一个轴:
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});
这比完全破坏你的整个图表/数据集,并重建一切要轻得多。
如果你在Angular项目中使用chart.js和Typescript,你可以试试下面的代码:
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"),
{
...
}
希望这对你有帮助。
首先将图表放入某个变量中,然后在下次初始化之前记录它
#检查myChart对象是否存在,然后扭曲它
if($scope.myChart) {
$scope.myChart.destroy();
}
$scope.myChart = new Chart(targetCanvas
您应该将图表保存为一个变量。在全局范围内,如果它是纯javascript,或者作为一个类属性,如果它是Angular。
那么你就可以使用这个引用来调用destroy()。
纯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();
}
}
对我来说这是有效的:
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.js有一个缺陷: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()
后销毁数据集对象。
对于那些喜欢我的人使用函数来创建几个图形并想要更新它们的块,只有函数。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 ...
在创建图表之前先声明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
})
- 鼠标悬停事件影响列表中所有行中的按钮,而不仅仅是特定按钮
- 如何在asp:linkButton上显示鼠标悬停事件上的图像
- 当鼠标也在触摸另一个元素时,d3.js鼠标悬停事件未被触发
- Jquery 悬停事件卡在克隆元素上
- 鼠标悬停事件不会触发以触发 D3 中的单击事件
- 在悬停事件中创建一次性操作
- Kango 浏览器扩展开发中的鼠标悬停事件弹出窗口
- 覆盖对话框悬停事件
- Raphael悬停事件和调整大小框在第三次鼠标悬停后发生故障
- 定位将禁用悬停选择器和鼠标悬停事件
- 在余烬中传播悬停事件
- 创建随机图像交换并禁止鼠标悬停事件
- 每个元素有多个鼠标悬停事件
- Highcharts点击事件返回“;悬停”;state而不是“state”;选择“;状态
- 使用JavaScript事件模拟悬停
- 如何使用if hasClass条件禁用jQuery mouseleave事件?//悬停动画
- onmouseover事件仅在第二次鼠标悬停后才起作用
- 在完整日历中添加事件悬停文本
- 在事件悬停或使用jquery单击时更改当前图像
- jquery mega下拉菜单插件(dcMegaMenu)如何改变事件悬停点击窗口大小