销毁chart.js条形图以在同一<canvas>中重绘其他图形

Uza*_*ade 37 javascript canvas graph chart.js

我使用Chart.js库绘制条形图,它工作正常,但现在我想破坏条形图并在同一画布中制作折线图.我尝试过这两种方法来清除画布:

var grapharea = document.getElementById("barChart").getContext("2d");

grapharea.destroy();

var myNewChart = new Chart(grapharea, { type: 'radar', data: barData, options: barOptions });
Run Code Online (Sandbox Code Playgroud)

第二种方式:

var grapharea = document.getElementById("barChart").getContext("2d");

grapharea.clear();

var myNewChart = new Chart(grapharea, { type: 'radar', data: barData, options: barOptions });
Run Code Online (Sandbox Code Playgroud)

我称之为正确吗?OnButtonClick我调用这个使用相同画布的函数.

xna*_*kos 74

要使用正确的方法,以便能够在同一画布上绘制另一个图表,是.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 });
Run Code Online (Sandbox Code Playgroud)

直接来自文档(在原型方法下):

.破坏()

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

// Example from the docs
var myLineChart = new Chart(ctx, config);
// Destroys a specific chart instance
myLineChart.destroy();
Run Code Online (Sandbox Code Playgroud)

它明确指出必须先调用此方法,然后才能将画布重新用于新图表.

.clear()稍后在同一部分中也会提到"将清除图表画布的功能.在动画帧之间广泛使用,但您可能会发现它很有用." 调用此方法后,图表将处于活动状态,因此,如果要将画布重新用于全新的图表,则不需要调用此方法.

老实说,在像你这样的情况下,我经常使用一个容器div来包装我,canvas并且每当我需要创建一个新图表时,我都会在其中放置一个新canvas元素div.然后我使用新创建canvas的新图表.如果你遇到过奇怪的行为,可能与当前图表之前占据画布的图表有关,也要记住这种方法.

  • 这种方法对我没有用。销毁方法什么也没做。 (3认同)
  • 回复 João Pimentel Ferreira - 将图表声明为变量,然后编写一个条件来检查它是否存在。`if (myChart) { myChart.destroy(); }` (2认同)

Nis*_*gar 47

ChartJs 的getChart(key) - 如果图表已创建,则从给定键查找图表实例。

  • 如果键是字符串,则它被解释为图表的 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();
}
//-- End of chart destroy   

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

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


It0*_*007 23

每次图表调用后删除画布,这对我有用

$("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, { .... });
Run Code Online (Sandbox Code Playgroud)

  • 这是个好主意,在普通 js 中 `document.getElementById( "sector-chart" ).remove(); 让 canvas = document.createElement('canvas'); canvas.setAttribute('id','chart'); canvas.setAttribute('宽度','300'); canvas.setAttribute('高度','100'); document.querySelector('#chart-container').appendChild(canvas); ` (3认同)
  • 谢谢,这是完美的工作... :) (2认同)

小智 7

你可以测试一下

 $('#canvas').replaceWith($('<canvas id="canvas" height="320px"></canvas>'));
Run Code Online (Sandbox Code Playgroud)

;)


bma*_*ovu 6

对于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();
});
Run Code Online (Sandbox Code Playgroud)

  • @RahulHindocha如果您无权访问变量,您可以通过查看“Chart.instances”对象来重新访问实例。从这里您可以执行 `Chart.instances[key].destroy()` 或 `Chart.instances[key].update()`。 (2认同)

sh6*_*210 5

也许有更好的方法,但没有适合我的答案。

document.querySelector("#chartReport").innerHTML = '<canvas id="myChart"></canvas>';
Run Code Online (Sandbox Code Playgroud)

我的 HTML 部分是

<div class="col-md-6 col-md-offset-3">
     <div id="chartReport">
         <canvas id="myChart"></canvas>
     </div>
</div>
Run Code Online (Sandbox Code Playgroud)


sab*_*and 5

我总是每页只使用 1 个图表。Destroy() 解决了问题。

 if (
        window.myLine !== undefined
        &&
        window.myLine !== null
    ) {
        window.myLine.destroy();
    }

    window.myLine = new Chart(graphCanvasCtx, config);
Run Code Online (Sandbox Code Playgroud)


Sur*_*rya 5

2020年的简单编辑:

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

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

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

希望它有效!

  • 这必须是唯一正确的选择。在没有首先检查是否有要销毁的东西的情况下,您不应该调用“destroy()”。此外,明确检查“图表实例”是正确的。我之前一直在检查“未定义”,它在某些情况下可能会导致问题。 (2认同)

ted*_*usa 5

以下是我针对给定画布 ID 创建新图表之前销毁 ChartJS 图表的策略。这有点暴力,但可以完成工作。

我创建了一个对象chartsByCanvasId,它跟踪从画布 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;
}

Run Code Online (Sandbox Code Playgroud)

然后,这就是销毁图表(如果存在)的方法

destroyChartIfNecessary(canvasId);
const myChart = new Chart(ctx, config);
registerNewChart(canvasId, myChart);

Run Code Online (Sandbox Code Playgroud)

请注意,创建图表后,我们立即将其“注册”到registerNewChart(). 这个注册步骤很重要,因为这是如何destroyChartIfNecessary()知道给定画布 id 的 ChartJS 对象已经存在。

这个策略的好处是,即使页面上有很多图表它也能工作,因为它通过画布 ID 跟踪 ChartJS 对象。