ChatGPT解决这个技术问题 Extra ChatGPT

如何从画布中清除图表以便无法触发悬停事件?

我正在使用 Chartjs 显示折线图,这很好用:

// get line chart canvas
var targetCanvas = document.getElementById('chartCanvas').getContext('2d');

// draw line chart
var chart = new Chart(targetCanvas).Line(chartData);

但是当我尝试更改图表的数据时会出现问题。我通过使用新数据点创建图表的新实例来更新图表,从而重新初始化画布。

这工作正常。但是,当我将鼠标悬停在新图表上时,如果我碰巧越过与旧图表上显示的点相对应的特定位置,悬停/标签仍会被触发,并且旧图表突然可见。当我的鼠标在这个位置时它仍然可见,当离开那个点时它会消失。我不希望显示旧图表。我想完全删除它。

在加载新图表之前,我尝试清除画布和现有图表。喜欢:

targetCanvas.clearRect(0,0, targetCanvas.canvas.width, targetCanvas.canvas.height);

chart.clear();

但到目前为止,这些都没有奏效。关于如何阻止这种情况发生的任何想法?

兄弟,这正是我遇到的问题。 “destroy()”方法不起作用,这让我很生气。
请问您是如何访问图表对象的?我遇到了同样的问题,我创建了一个图表,然后在处理按钮单击时我需要销毁它,但它的功能完全不同,我找不到通过画布或上下文访问图表对象的方法对象。
有一个针对此问题的错误打开,请在此处查看。 github.com/jtblin/angular-chart.js/issues/187
有这个问题。创建/重新创建 stackoverflow.com/a/51882403/1181367 的解决方案

n
neaumusic

我对此有很大的问题

首先我尝试了 .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);
};

像冠军一样工作。如果有人知道 Chart.js 版本 2 是否修复了这个问题,请在此处发布。我想知道destroy是否坏了,或者我们是否使用不正确。
好的!谢谢!我刚刚添加了 $('#results-graph').remove(); $('#graph-container').append('');在创建图表之前。
.destroy() 应该可以正常工作。如果没有,在调用 .destroy() 绘制新图表后,使用 setTimeout()
这是唯一对我有用的解决方案,非常感谢,但是对于宽度和高度,如果你已经将它们设置为固定,你应该在重置函数中将它们重置为相同的值
使用 chartjs 2.8.0 对我来说 destroy() 失败了,但您的解决方案刚刚奏效!就我而言,我只在 new Chart(document.getElementById("myCanvas") 之前使用了 $('#results-graph').remove(); $('#graph-container').append('<canvas id="results-graph"><canvas>');
R
Roberto Pierpaoli

几个小时前我也遇到了同样的问题。

".clear()" 方法实际上清除了画布,但(显然)它使对象保持活跃和反应。

仔细阅读the official documentation,在“高级用法”部分,我注意到方法“.destroy()”,描述如下:

“使用它来销毁创建的任何图表实例。这将清除存储在 Chart.js 中的图表对象的所有引用,以及 Chart.js 附加的任何关联事件侦听器。”

它实际上做了它声称的事情,对我来说效果很好,我建议你试一试。


你能举个例子吗?我曾尝试多次使用阻塞,但它从来没有用过。我总是收到该方法不存在的错误。
( this.chart).destroy();
这是正确的答案。有关将来的参考资料,请参阅:stackoverflow.com/questions/40056555/…
x
xchiltonx
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});
}

这是最好的选择
好一个。谢谢
E
Eric

这是唯一对我有用的东西:

document.getElementById("chartContainer").innerHTML = '&nbsp;';
document.getElementById("chartContainer").innerHTML = '<canvas id="myCanvas"></canvas>';
var ctx = document.getElementById("myCanvas").getContext("2d");

J
Javier Muñoz

我在这里遇到了同样的问题......我尝试使用 destroy() 和 clear() 方法,但没有成功。

我通过以下方式解决了它:

HTML:

<div id="pieChartContent">
    <canvas id="pieChart" width="300" height="300"></canvas>
</div>

Javascript:

var pieChartContent = document.getElementById('pieChartContent');
pieChartContent.innerHTML = '&nbsp;';
$('#pieChartContent').append('<canvas id="pieChart" width="300" height="300"><canvas>');

ctx = $("#pieChart").get(0).getContext("2d");        
var myPieChart = new Chart(ctx).Pie(data, options);

它对我来说很完美......我希望它有所帮助。


S
Sam G

我们可以更新 Chart.js V2.0 中的图表数据如下:

var myChart = new Chart(ctx, data);
myChart.config.data = new_data;
myChart.update();

我同意这是一个更好的解决方案 - Destroy 过于激进,而我们真正想要的只是重新启动“数据”。
谢啦!!这就是我需要的。投票赞成!
N
Nicholas Macharia

这对我来说效果很好

    var ctx = $("#mycanvas");
     var LineGraph = new Chart(ctx, {
        type: 'line',
        data: chartdata});
        LineGraph.destroy();

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


这种方式对我来说可以正常工作,看起来它破坏了悬停回调。坦克这么多!
S
Surya

2020 年的简单编辑:

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

检查图表变量是否已经初始化为Chart,如果是,则将其销毁并创建一个新的,即使您可以创建另一个同名的变量。下面是代码:

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

希望它有效!


N
Nishi Bangar

最好使用 Chart.js 的特定功能来初步检查现有图表实例,然后执行销毁或清除,以便重用相同的画布元素来呈现另一个图表,而不是从 JS 中处理 HTML 元素。

ChartJs 的 getChart(key) - 从给定键中查找图表实例。

如果键是字符串,则将其解释为图表的 Canvas 元素的 ID。

键也可以是 CanvasRenderingContext2D 或 HTMLDOMElement。

注意:如果没有找到图表,这将返回 undefined。如果找到图表的实例,则表示该图表必须先前已创建。

// JS - 销毁退出的图表实例以重用 元素 let chartStatus = Chart.getChart("myChart"); // id if (chartStatus != undefined) { chartStatus.destroy(); //(或) // chartStatus.clear(); } //-- 图表结束销毁 var chartCanvas = $('#myChart'); // id chartInstance = new Chart(chartCanvas, { type: 'line', data: data });

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


G
Gato de Schrödinger

补充亚当的答案

使用香草 JS:

document.getElementById("结果图").remove(); //canvas div = document.querySelector("#graph-container"); //canvas 父元素 div.insertAdjacentHTML("afterbegin", ""); //再次添加画布


a
aggaton

使用 CanvasJS,这适用于我清除图表和其他所有内容,也可能对您有用,允许您在其他地方的每个处理之前完全设置您的画布/图表:

var myDiv= document.getElementById("my_chart_container{0}";
myDiv.innerHTML = "";

对我来说,上述方法都不起作用。这非常有效。非常感谢。
C
Chris

我也无法让 .destroy() 工作,所以这就是我正在做的事情。 chart_parent div 是我希望画布出现的地方。我需要每次调整画布大小,所以这个答案是上述答案的扩展。

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

z
zebus3d

当您创建一个新的 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


J
Jay

这对我有用。在您的 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;
}`

T
T.S

由于破坏类型会破坏“一切”,因此当您真正想要的只是“重置数据”时,这是一种廉价而简单的解决方案。将数据集重置为空数组也可以正常工作。因此,如果您有一个带有标签的数据集,并且每边都有一个轴:

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

或者,取决于您是否使用二维数据集:

window.myLine2.data.datasets[0].data.push({ x: x, y: y});

这将比完全破坏整个图表/数据集并重建所有内容要轻得多。


P
Pulak Kanti Bhattacharyya

如果您在带有 Typescript 的 Angular 项目中使用 chart.js,您可以尝试以下操作;

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>

Q
Qammar Feroz

我们所做的是,在初始化新图表之前,删除/销毁预览图表实例,如果已经存在,则创建一个新图表,例如

if(myGraf != undefined)
    myGraf.destroy();
    myGraf= new Chart(document.getElementById("CanvasID"),
    { 
      ...
    }

希望这可以帮助。


V
Vaimeo

首先将图表放入某个变量中,然后在下次初始化之前对其进行历史记录

#检查myChart对象是否存在然后扭曲它

    if($scope.myChart) {
      $scope.myChart.destroy();
    }

    $scope.myChart  = new Chart(targetCanvas

P
Pedro Alvares

您应该将图表保存为变量。在全局范围内,如果它是纯 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();
    }
}

S
Scrapie

对我来说,这很有效:

var in_canvas = document.getElementById('chart_holder'); //如果存在则删除画布 while (in_canvas.hasChildNodes()) { in_canvas.removeChild(in_canvas.lastChild); } //插入画布 var newDiv = document.createElement('canvas'); in_canvas.appendChild(newDiv); newDiv.id = "我的图表";


M
Michael Parker

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() 后销毁数据集对象。


S
SNS - Web et Informatique

对于像我一样使用函数创建多个图形并想更新它们的块的人,只有函数 .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 ...

2
2 revs, 2 users 68%

只需在创建图表之前声明 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
})

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅