[英]Destroy chart.js bar graph to redraw other graph in same <canvas>
我正在使用Chart.js庫繪制條形圖,它工作正常,但現在我想破壞條形圖並在同一個canvas中制作折線圖。 我試過這兩種方法來清除canvas:
var grapharea = document.getElementById("barChart").getContext("2d");
grapharea.destroy();
var myNewChart = new Chart(grapharea, { type: 'radar', data: barData, options: barOptions });
第二種方式:
var grapharea = document.getElementById("barChart").getContext("2d");
grapharea.clear();
var myNewChart = new Chart(grapharea, { type: 'radar', data: barData, options: barOptions });
我說得對嗎? OnButtonClick 我稱之為 function,它使用相同的 canvas。
為了能夠在同一畫布上繪制另一個圖表,正確的使用方法是.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 });
直接來自 文檔(在原型方法下) :
.銷毀()
使用它來銷毀任何創建的圖表實例。 這將清除 Chart.js 中存儲到圖表對象的所有引用,以及 Chart.js 附加的任何關聯事件偵聽器。 這必須在畫布重新用於新圖表之前調用。
// Example from the docs
var myLineChart = new Chart(ctx, config);
// Destroys a specific chart instance
myLineChart.destroy();
它明確指出必須先調用此方法,然后才能將畫布重新用於新圖表。
.clear()
也在后面與“將清除圖表畫布的函數相同的部分中提到。在動畫幀之間廣泛使用,但您可能會發現它很有用。” 調用此方法后,圖表將保持良好狀態,因此如果您想將畫布重用於全新的圖表,則不應調用此方法。
不過,老實說,在像您這樣的情況下,我經常使用容器div
來包裝我的canvas
並且每當我需要創建新圖表時,我都會在這個div
放置一個新的canvas
元素。 然后我將這個新創建的canvas
用於新圖表。 如果您遇到過奇怪的行為,可能與圖表在當前圖表之前占據畫布有關,也請記住這種方法。
每次圖表調用后刪除畫布,這對我有用
$("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, { .... });
對於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();
});
也許有更好的方法,但沒有適合我的答案。
document.querySelector("#chartReport").innerHTML = '<canvas id="myChart"></canvas>';
我的 HTML 部分是
<div class="col-md-6 col-md-offset-3">
<div id="chartReport">
<canvas id="myChart"></canvas>
</div>
</div>
2020 年的簡單編輯:
這對我有用。 通過使其擁有窗口來將圖表更改為全局(將聲明從var myChart
更改為window myChart
)
檢查chart變量是否已經初始化為Chart,如果是,銷毀它並創建一個新的,即使你可以創建另一個同名的。 下面是代碼:
if(window.myChart instanceof Chart)
{
window.myChart.destroy();
}
var ctx = document.getElementById('myChart').getContext("2d");
希望它有效!
我現在使用的是 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);
你可以測試這個
$('#canvas').replaceWith($('<canvas id="canvas" height="320px"></canvas>'));
;)
這是我在為給定的畫布 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 對象。
我總是只使用 1 個圖/頁。 Destroy() 解決了這些問題。
if (
window.myLine !== undefined
&&
window.myLine !== null
) {
window.myLine.destroy();
}
window.myLine = new Chart(graphCanvasCtx, config);
ChartJs 的getChart(key) - 如果圖表已經創建,則從給定的鍵中查找圖表實例。
注意:如果沒有找到圖表,這將返回undefined 。 如果找到圖表的實例,則表示該圖表必須先前已創建。
// 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 });
<!-- HTML -Line Graph - Chart.js --> <div class="container-fluid" id="chartContainer"> <canvas id="myChart" width="400" height="150"> </canvas> </div>
這種方法將使您免於從 JS 內部刪除 - 創建 - 將 Canvas 元素附加到 DIV 中。
為了解決這個問題,我使用了 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
}
創建一個全局對象:
window['chart-' + chartId] = new Chart(...);
訪問和銷毀以進行重繪:
if ( window['chart-' + chartId] != undefined ) {
window['chart-' + chartId].destroy();
}
這將解決圖表在多次 ajax 調用中多次更新時變慢的問題:
只需在啟動圖表之前添加此代碼:
$('.chartjs-size-monitor').each(function(){
$(this).remove();
})
var grapharea = document.getElementById("barChart").getContext("2d");
我遇到了同樣的問題,我刪除了畫布元素並重新創建了畫布元素,然后再次渲染了一些延遲。
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)
我設法找到了一個與 destroy 方法一起使用的解決方案,並允許在不刪除和重新創建畫布的情況下重用畫布,同時它是較少的資源消耗者。
首先,聲明var chart為 global 並創建一個布爾值來檢查 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
var chart = new Chart(ctx, {
[.....]
});
return chart;
函數“loadscript”是基於這個答案定制的: 如何在另一個 JavaScript 文件中包含一個 JavaScript 文件?
這是:
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);
}
它就像一個魅力。
對我來說,它似乎與核心 javascript 類似如下(假設圖表 min 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);
}
如果您在一頁上有許多圖表,那么構建數據結構來保存現有圖表的列表是很復雜的。 在 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);
我不知道我花了多少小時來處理這個問題。
讓我們假設您的 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);
.
.
}
從...更改新圖表變量
var yourChart= new Chart(ctx1).Line(barChartData1, {animation: false});
到
window.yourChart= new Chart(ctx1).Line(barChartData1, {animation: false});
然后
if(window.yourChart!= null)
{
window.yourChart.destroy();
}
var doc1 = document.getElementById("stockPrice");
var ctx1 = doc1.getContext("2d");
window.yourChart = new Chart(ctx1).Bar(barChartData1, {animation: false});
改變這個: var myChart = new Chart(ctx, {...
到
如果(window.myChartAnything != 未定義)
window.Anything.destroy();
window.Anything = new Chart(ctx, {...
這在我的網頁上很震撼。
我對此略有不同。 首先在我的 js 中,我定義了一個 map,如下所示。
var chartContext = new Map();
當我填充這個圖表時,我插入一個鍵值對,就像這個值是圖表 object 它自己和鍵是那個 canvas 的 id。
chartContext.set(chartid, chartObject);
在此之后,當我需要再次重新填充/重新渲染相同的 canvas 時,我會執行以下操作。
if (chartContext.has(chartid)) {
tempchartContext = chartContext.get(chartid);
if (tempchartContext instanceof Chart) {
tempchartContext.destroy();
}
}
通過這種方式,舊的圖表上下文被破壞了。
在制作新圖表后,我調用以下代碼再次更新相同的 canvas
我在此示例中使用 Angular 並發現通過執行以下操作很容易
import Chart, { ChartConfiguration } from 'chart.js/auto';
export class ReportsComponent implements OnInit {
chart1: Chart;
ngOnInit(): void {
this.initGraphs(); // logic for creating your charts
this.drawGraphs(data) // populate the chart and update graph
}
initGraphs(){
this.chart1= new Chart(...)
}
drawGraphs(data){ // just an example of how you might populate your chart
for (const total of Object.values(data.gender)) {
this.chart1.data.datasets[0].data.push(+total);
}
this.chart1.update(); // to override the default empty datasets on the chart config
}
onUpdate(){
const filteredData = {...} // this would be the new data you want to show
this.chart1.destroy();
this.initGraphs();
this.drawGraphs(filteredData);
}
}
所以是的,您使用.destroy()
來銷毀創建的任何圖表實例。 但是您必須再次創建圖表才能將其呈現在您的屏幕上
Mais simples que usar a API do charts.js, aqui foi usando o Jquery, JS puro também vai funcionar:
HTML
<div id="graficoSituacoesPedidos" class="col-12">
<canvas id="myChart"></canvas>
</div>
JS
$('#myChart').remove();
$('#graficoSituacoesPedidos').append('<canvas id="myChart"></canvas>');
// Abaixo recriar o grafico。 Com JS puro funciona também。
這在角度上對我有用
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();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.