簡體   English   中英

如何從畫布中清除圖表以便無法觸發懸停事件?

[英]How to clear a chart from a canvas so that hover events cannot be triggered?

我正在使用 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();

但到目前為止,這些都沒有奏效。 關於如何阻止這種情況發生的任何想法?

我在這方面遇到了很大的問題

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

幾個小時前我遇到了同樣的問題。

“.clear()”方法實際上清除了畫布,但(顯然)它使對象保持活躍和反應。

仔細閱讀官方文檔,在“高級用法”部分,我注意到了“.destroy()”方法,描述如下:

“使用它來銷毀創建的任何圖表實例。這將清除存儲到 Chart.js 中圖表對象的任何引用,以及 Chart.js 附加的任何關聯事件偵聽器。”

它實際上做到了它聲稱的那樣並且對我來說效果很好,我建議您嘗試一下。

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

這是唯一對我有用的東西:

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

我在這里遇到了同樣的問題......我嘗試使用 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);

它對我來說很完美......我希望它有所幫助。

我們可以在 Chart.js V2.0 中更新圖表數據如下:

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

這對我來說非常有效

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

使用.destroy this 來銷毀創建的任何圖表實例。 這將清除 Chart.js 中存儲到圖表對象的所有引用,以及 Chart.js 附加的任何關聯事件偵聽器。 這必須在畫布重新用於新圖表之前調用。

2020 年的簡單編輯:

這對我有用。 通過使其擁有窗口來將圖表更改為全局(將聲明從var myChart更改為window myChart

檢查chart變量是否已經初始化為Chart,如果是,銷毀它並創建一個新的,即使你可以創建另一個同名的。 下面是代碼:

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

希望它有效!

補充亞當的答案

使用香草 JS:

 document.getElementById("results-graph").remove(); //canvas div = document.querySelector("#graph-container"); //canvas parent element div.insertAdjacentHTML("afterbegin", "<canvas id='results-graph'></canvas>"); //adding the canvas again

最好使用 Chart.js 特定功能來初步檢查現有圖表實例,然后執行銷毀或清除,以便重用相同的畫布元素來呈現另一個圖表,而不是從 JS 內部處理 HTML 元素。

ChartJs 的getChart(key) - 從給定的鍵中找到圖表實例。

  • 如果鍵是字符串,則將其解釋為圖表的 Canvas 元素的 ID。
  • 鍵也可以是 CanvasRenderingContext2D 或 HTMLDOMElement。

注意:如果沒有找到圖表,這將返回undefined 如果找到圖表的實例,則表示該圖表必須先前已創建。

 // JS - Destroy exiting Chart Instance to reuse <canvas> element let chartStatus = Chart.getChart("myChart"); // <canvas> id if (chartStatus != undefined) { chartStatus.destroy(); //(or) // chartStatus.clear(); } //-- 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 中。

使用 CanvasJS,這適用於我清除圖表和其他所有內容,也可能適用於您,允許您在其他地方的每次處理之前完全設置畫布/圖表:

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

我也無法讓 .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>');

當您創建一個新的 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

這對我有用。 在 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;
}`

如果您在帶有 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>

我們所做的是,在初始化新圖表之前,移除/銷毀預覽圖表實例,如果已經存在,則創建一個新圖表,例如

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

希望這可以幫助。

首先將圖表放在某個變量中,然后在下次初始化之前將其歷史化

#檢查myChart對象是否存在然后扭曲它

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

    $scope.myChart  = new Chart(targetCanvas

您應該將圖表保存為變量。 在全局范圍內,如果它是純 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();
    }
}

對我來說這有效:

 var in_canvas = document.getElementById('chart_holder'); //remove canvas if present while (in_canvas.hasChildNodes()) { in_canvas.removeChild(in_canvas.lastChild); } //insert canvas var newDiv = document.createElement('canvas'); in_canvas.appendChild(newDiv); newDiv.id = "myChart";

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()上刪除此屬性。

如果您使用舊的DataSet對象不去除._meta property ,chart.js之將新的數據集添加到._meta不刪除以前的數據。 因此,在每個圖表重新初始化時,您的數據集對象會累積所有以前的數據。

為了避免這種情況,在調用Chart.destroy()之后銷毀數據集對象。

由於銷毀會破壞“一切”,因此當您真正想要的只是“重置數據”時,一個廉價而簡單的解決方案。 將數據集重置為空數組也可以正常工作。 因此,如果您有一個帶有標簽的數據集,並且每邊都有一個軸:

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

它比完全銷毀整個圖表/數據集並重建所有內容要輕得多。

對於那些喜歡我的人使用一個函數來創建多個圖形並也想將它們更新為一個塊,只有函數 .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 ...

在創建圖表之前聲明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
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM