我正在使用 Chart.js 库来绘制条形图,它工作正常,但现在我要销毁条形图并在同一画布中制作折线图。我试过这两种方法来清除画布:
%
第二种方式:
var grapharea = document.getElementById("barChart").getContext("2d");
grapharea.destroy();
var myNewChart = new Chart(grapharea, { type: 'radar', data: barData, options: barOptions });
我称之为正确吗? OnButtonClick我调用这个使用相同画布的函数。
答案 0 :(得分:67)
为了能够在同一画布上绘制另一个图表,使用的正确方法是.destroy()
。您必须在先前创建的图表对象上调用它。您也可以对两个图表使用相同的变量。
var grapharea = document.getElementById("barChart").getContext("2d");
var myChart = new Chart(grapharea, { type: 'bar', data: barData, options: barOptions });
myChart.destroy();
myChart = new Chart(grapharea, { type: 'radar', data: barData, options: barOptions });
直接来自docs (under Prototype Methods):
.destroy()
使用此选项可以销毁所创建的任何图表实例。这将清除Chart.js中存储到图表对象的任何引用,以及Chart.js附加的任何关联事件侦听器。必须在将画布重新用于新图表之前调用它。
// Example from the docs
var myLineChart = new Chart(ctx, config);
// Destroys a specific chart instance
myLineChart.destroy();
它明确指出必须先调用此方法,然后才能将画布重新用于新图表。
.clear()
稍后在与“清除图表画布”的功能相同的部分中也会提到。在动画帧之间广泛使用,但您可能会发现它很有用。调用此方法后,图表将处于活动状态,因此,如果要将画布重新用于全新的图表,则不需要调用该方法。
老实说,在像你这样的情况下,我经常使用容器div
来包裹我的canvas
,每当我需要创建一个新图表时,我都会放置一个新的{{}这个canvas
中的1}}元素。然后我将这个新创建的div
用于新图表。如果您遇到过可能与当前图表之前占据画布的图表有关的奇怪行为,也应考虑这种方法。
答案 1 :(得分:21)
每次图表调用后删除画布,这对我有用
$("canvas#chartreport").remove();
$("div.chartreport").append('<canvas id="chartreport" class="animated fadeIn" height="150"></canvas>');
var ctx = document.getElementById("chartreport").getContext("2d");
chartreport= new Chart(ctx, { .... });
答案 2 :(得分:2)
对于 ChartJS v2.x ,您可以使用update()更新图表数据,而无需显式销毁和创建画布。
var chart_ctx = document.getElementById("chart").getContext("2d");
var chart = new Chart(chart_ctx, {
type: "pie",
data: {}
options: {}
}
$.ajax({
...
}).done(function (response) {
chart.data = response;
chart.update();
});
答案 3 :(得分:2)
2020年的简单修改:
这对我有用。通过使其成为窗口所有者来将图表更改为全局(将声明从var myChart
更改为window myChart
)
检查chart变量是否已经初始化为Chart,如果是,则销毁它并创建一个新变量,即使您可以使用相同的名称创建另一个变量。下面是代码:
if(window.myChart instanceof Chart)
{
window.myChart.destroy();
}
var ctx = document.getElementById('myChart').getContext("2d");
希望它能起作用!
答案 4 :(得分:1)
截至目前,我正在使用Chart.js 2.7.2。在我的应用程序中,我正在创建多个图表,并且需要一种方法来访问它们以正确“替换”其数据并修复悬停时显示的“旧图表”。我尝试过的所有答案都没有奏效。
这是一种使用一个或多个图表进行管理的方法:
将图表存储在全球范围内
var charts=[]; // global
创建图表的功能
function createChart(id, type, labels, data)
{
// for multiple datasets
var datasets=[];
data.forEach(function(set) {
datasets.push({
label: set.label,
data: set.data
});
});
var config = {
type: type,
data: {
labels: labels,
datasets: datasets
}
};
if(typeof charts[id] == "undefined") // see if passed id exists
{
// doesn't, so create it
charts[id]= new (function(){
this.ctx=$(id); // canvas el
this.chart=new Chart(this.ctx, config);
})();
console.log('created chart '+charts[id].chart.canvas.id);
}
else
{
charts[id].chart.destroy(); // "destroy" the "old chart"
charts[id].chart=new Chart(charts[id].ctx, config); // create the chart with same id and el
console.log('replaced chart '+charts[id].chart.canvas.id);
}
// just to see all instances
Chart.helpers.each(Chart.instances, function(instance){
console.log('found instance '+instance.chart.canvas.id)
})
}
对于您的每个画布元素,例如:
<canvas id="thiscanvasid"></canvas>
使用函数创建/替换图表
createChart('#thiscanvasid', 'bar', json.labels, json.datasets);
答案 5 :(得分:1)
您可以测试
$('#canvas').replaceWith($('<canvas id="canvas" height="320px"></canvas>'));
;)
答案 6 :(得分:1)
这是我在为给定的画布 ID 创建新图表之前销毁 ChartJS 图表的策略。这有点蛮力,但可以完成工作。
我创建了一个对象,用于跟踪从画布 ID 到关联 ChartJS 对象的映射,并且我将在创建新对象之前检查该对象是否存在任何要销毁的现有 ChartJS 对象。
看看这里:
// Helper object and functions
const chartsByCanvasId = {};
const destroyChartIfNecessary = (canvasId) => {
if (chartsByCanvasId[canvasId]) {
chartsByCanvasId[canvasId].destroy();
}
}
const registerNewChart = (canvasId, chart) => {
chartsByCanvasId[canvasId] = chart;
}
然后,如果图表存在,这就是如何销毁图表
destroyChartIfNecessary(canvasId);
const myChart = new Chart(ctx, config);
registerNewChart(canvasId, myChart);
请注意,在创建图表后,我们会立即使用 registerNewChart()
对其进行“注册”。这个注册步骤很重要,因为这就是 destroyChartIfNecessary()
如何知道一个给定画布 ID 的 ChartJS 对象已经存在。
这个策略的好处是,即使页面上有很多图表,它也能工作,因为它通过画布 ID 跟踪 ChartJS 对象。
答案 7 :(得分:0)
我不知道我花了多少小时来处理这个问题。
假设您的 html 包含该内容
<div id="soner" class="card-body customerDonutChart">
<canvas id="customerDonutChart" style="min-height: 250px; height: 250px; max-height: 250px; max-width: 100%;"></canvas>
</div>
注意解决问题所必需的 <div id="soner"
部分。
function myChartJsCaller()
{
document.getElementById("soner").innerHTML = '<canvas id="customerDonutChart" style="min-height: 250px; height: 250px; max-height: 250px; max-width: 100%;"></canvas>';
// here is important, your ctx = blabla must be below after changing innerHTML
let ctx = document.getElementById(selector);
.
.
}
答案 8 :(得分:0)
如果您在一页上有很多图表,那么构建数据结构来保存现有图表的列表是很复杂的。在 chart.js 3.5.0 中更容易测试图表画布是否已被使用。不需要单独的数据结构:
// Chart may previously have been shown or not, so the chart may need creating or updating.
// Vue messes with the DOM, so you can't just "update" the chart as per the docs.
var canv = this.$refs['canvas'];
const oldChart = Chart.getChart(canv);
if (typeof oldChart !== 'undefined') {
oldChart.destroy();
}
new Chart(canv.getContext('2d'), this.config);
答案 9 :(得分:0)
对我来说,它似乎与核心 javascript 的工作方式如下(假设图表最小 js 已经加载):
const data = {
labels : graphDataLabels,
datasets: [{
label: 'Sentiment Intensity Distribution',
data: dataValues, //[300, 50, 100],
backgroundColor: [
"#0D5265",
"#32DAC8",
"#FF8300"
],
hoverOffset: 4
}]
};
const config = {
type: 'pie',
data: data
};
var ctx = document.getElementById('pieChart').getContext('2d');
if(ctx.pieChart){
pieChart = null;
}else{
pieChart = new Chart(ctx, config);
}
答案 10 :(得分:0)
我设法找到了一个解决方案,它可以与 destroy 方法一起使用,并允许在不删除和重新创建画布的情况下重用画布,同时它的资源消耗更少。
首先,将var chart声明为全局并创建一个布尔值来检查js是否加载
var chart;
var graphScriptLoaded = false;
下一部分很好,因为它只在需要图形时加载js,节省了加载页面的时间,同时它可以让您了解是否是第一次执行与否。
//load graph just when needed and destry existing istances
if (!Boolean(graphScriptLoaded)) {
loadScript('https://cdn.jsdelivr.net/npm/chart.js@2.8.0', function(){
graphScriptLoaded = true;
chart=graphs_init(i_arr, spent_arr);
});
} else {
chart.destroy();
chart=graphs_init(i_arr, spent_arr);
}
然后,在创建图表的函数中,简单地返回图表变量
var chart = new Chart(ctx, {
[.....]
});
return chart;
函数“loadscript”是基于这个答案定制的: How do I include a JavaScript file in another JavaScript file?
这里是:
function loadScript(url, callback){
var script = document.createElement("script")
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
它就像一个魅力。
答案 11 :(得分:0)
我遇到了同样的问题,我删除了canvas元素并重新创建了canvas元素,然后再次进行渲染。
var element = document.getElementById("canvasId");
element.parentNode.removeChild(element);
var canv = document.createElement("canvas");
canv.setAttribute("id","canvasId");
canv.style.height = "20vw"; // give height and width as per the requirement
canv.style.width = "20vw";
setTimeout(()=>{
var grapharea = document.getElementById("canvasId").getContext("2d");
},500)
答案 12 :(得分:0)
这将解决您的图表在多次ajax调用中多次更新时变慢的问题:
只需在启动图表之前添加以下代码:
$('.chartjs-size-monitor').each(function(){
$(this).remove();
})
var grapharea = document.getElementById("barChart").getContext("2d");
答案 13 :(得分:0)
创建一个全局对象:
window['chart-' + chartId] = new Chart(...);
访问并销毁以进行重绘:
if ( window['chart-' + chartId] != undefined ) {
window['chart-' + chartId].destroy();
}
答案 14 :(得分:0)
我总是只使用1个图形/页面。 Destroy()解决了问题。
if (
window.myLine !== undefined
&&
window.myLine !== null
) {
window.myLine.destroy();
}
window.myLine = new Chart(graphCanvasCtx, config);
答案 15 :(得分:0)
也许有更好的方法,但是没有答案适合我。
df.col.str.rsplit(".",1).str[0]
我的HTML部分是
document.querySelector("#chartReport").innerHTML = '<canvas id="myChart"></canvas>';
答案 16 :(得分:0)
为了解决此问题,我使用了jQuery的add()
和remove()
方法来清理画布。我要删除组件,然后再绘制之前,我要使用jQuery的append()
方法以相同的ID再次附加画布。
redraw(){
$("#myChart").remove();// removing previous canvas element
//change the data values or add new values for new graph
$("#chart_box").after("<canvas id='myChart'></canvas>");
// again adding a new canvas element with same id
generateGraph();// calling the main graph generating function
}
答案 17 :(得分:-1)
这对我有用
removeHTML() {
let chart = <HTMLCanvasElement>document.getElementById("myChart");
let chart2 = <HTMLCanvasElement>document.getElementById("myChart2");
if(chart){
chart.remove()
}
if(chart2){
chart2.remove()
}
}
ngOnDestroy(): void {
this.removeHTML();
}