Javascript 销毁chart.js条形图以重新绘制同一图形<;帆布>;

Javascript 销毁chart.js条形图以重新绘制同一图形<;帆布>;,javascript,canvas,graph,chart.js,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: barOpt

我正在使用Chart.js库绘制一个条形图,它工作正常,但现在我想销毁条形图,并在同一个画布中制作一个线形图。我尝试了以下两种方法来清除画布:

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

我说得对吗?OnButton单击我调用这个使用相同画布的函数。

为了能够在同一画布上绘制另一个图表,正确的方法是
.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对象的任何引用,以及chart.js附加的任何关联事件侦听器。必须在画布重新用于新图表之前调用此函数

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

.clear()
在后面的同一节中还提到了函数“将清除图表画布。在动画帧之间广泛使用,但您可能会发现它很有用。”调用此方法后,图表将处于活动状态,因此这不是要调用的方法,如果您想为一个全新的图表重复使用画布


不过,老实说,在像您这样的情况下,我经常使用容器
div
来包装我的
canvas
,每当我需要创建新图表时,我都会在
div
中放置一个新的
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, { .... });
$(“画布#图表报告”).remove();
$(“div.chartreport”)。附加(“”);
var ctx=document.getElementById(“chartreport”).getContext(“2d”);
chartreport=新图表(ctx,{…});

对于ChartJS v2.x您可以使用更新图表数据,而无需显式销毁和创建画布

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

我现在正在使用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>

为了解决这个问题,我使用了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 

}
redraw(){
$(“#myChart”).remove();//删除上一个画布元素
//更改数据值或为新图形添加新值
$(“#图表框”)。在(“)之后;
//再次添加具有相同id的新画布元素
generateGraph();//调用主图形生成函数
}

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

document.querySelector("#chartReport").innerHTML = '<canvas id="myChart"></canvas>';
document.querySelector(“#chartReport”).innerHTML=”;
我的HTML部分是

<div class="col-md-6 col-md-offset-3">
     <div id="chartReport">
         <canvas id="myChart"></canvas>
     </div>
</div>

您可以对此进行测试

 $('#canvas').replaceWith($('<canvas id="canvas" height="320px"></canvas>'));
$('#canvas')。替换为($('');

)()

我总是只使用一张图表/页。他解决了这些问题

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

    window.myLine = new Chart(graphCanvasCtx, config);
2020年的简单编辑:

这对我有用。通过将图表设置为窗口所有,将其更改为全局(将声明从
var myChart
更改为
window myChart

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

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

希望它能起作用

创建全局对象:

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

我遇到了同样的问题,我删除了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)

我设法找到了一个解决方案,它与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);
}
然后,在创建图形的函数中,只需返回chart var

var chart = new Chart(ctx, {
[.....]
});
return chart;
函数“loadscript”是根据以下答案定制的:

这是:

    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中的工作方式如下(假设chart min js已经加载):


这对我来说很有用

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();
}
removeHTML(){
让chart=document.getElementById(“myChart”);
让chart2=document.getElementById(“myChart2”);
如果(图表){
图表。删除()
}
如果(图2){
图2.删除()
}
}
ngOnDestroy():void{
this.removeHTML();
}

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

我创建了一个对象,该对象跟踪从画布id到关联的ChartJS对象的映射,在创建新对象之前,我将检查该对象是否有任何现有的ChartJS对象要销毁 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); }
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);
    }
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();
}

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