호버 이벤트가 트리거되지 않도록 캔버스에서 차트를 지우는 방법은 무엇입니까?


109

나는 Chartjs를 사용하여 선 차트를 표시하고 있으며 잘 작동합니다.

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

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

하지만 차트의 데이터를 변경하려고 할 때 문제가 발생합니다. 새 데이터 포인트로 Chart의 새 인스턴스를 만들고 캔버스를 다시 초기화하여 그래프를 업데이트합니다.

이것은 잘 작동합니다. 그러나 새 차트 위로 마우스를 가져 가면 이전 차트에 표시된 포인트에 해당하는 특정 위치를지나 가면 마우스 오버 / 레이블이 여전히 트리거되고 갑자기 이전 차트가 표시됩니다. 내 마우스가이 위치에있는 동안에는 계속 표시되고 해당 지점에서 벗어나면 사라집니다. 이전 차트를 표시하고 싶지 않습니다. 완전히 제거하고 싶습니다.

새 차트를로드하기 전에 캔버스와 기존 차트를 모두 지우려고했습니다. 처럼:

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

과

chart.clear();

그러나 이들 중 어느 것도 지금까지 작동하지 않았습니다. 이런 일이 발생하는 것을 막을 수있는 방법에 대한 아이디어가 있습니까?


18
야,이게 내가 가진 문제 야. "destroy ()"메서드가 작동하지 않고 짜증이납니다.
— neaumusic

차트 개체에 액세스하는 방법을 물어봐도 될까요? 같은 문제가 발생하여 차트를 만든 다음 버튼을 클릭하여 삭제해야하는데 완전히 다른 기능에 있으며 캔버스 또는 컨텍스트를 통해 차트 개체에 액세스하는 방법을 찾을 수 없습니다. 사물.
— Matt Williams

이 문제에 대해 열린 버그가 있습니다. 여기에서 확인하십시오. github.com/jtblin/angular-chart.js/issues/187
— MDT

이 문제가 있었다. 생성 / 재생성 솔루션 stackoverflow.com/a/51882403/1181367
— Chris

답변:


142

나는 이것에 큰 문제가 있었다

먼저 시도한 .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);
};

2
챔피언처럼 일했습니다. Chart.js 버전 2가이 문제를 해결하는지 아는 사람이 있으면 여기에 게시하십시오. destroy가 깨 졌는지 아니면 잘못 사용하고 있는지 궁금합니다.
— TheLettuceMaster 2015

2
좋은! 감사! 방금 $ ( '# results-graph'). remove (); $ ( '# graph-container'). append ( '<canvas id = "results-graph"> <canvas>'); 차트 생성 전에.
— Ignacio

.destroy ()가 제대로 작동합니다. 그렇지 않은 경우 .destroy ()를 호출하여 새 차트를
— 그린 후

그 유일한 해결책은 나에게 많은 감사를했다지만, 폭과 높이의 당신은 이미 당신이 초기화 함수에서 같은 값으로 재설정해야 고정 설정하는 경우
— 샌디 Elkassar을

2
chartjs 2.8.0에서 destroy ()가 실패했지만 솔루션이 작동했습니다! 제 경우 $('#results-graph').remove(); $('#graph-container').append('<canvas id="results-graph"><canvas>');에는new Chart(document.getElementById("myCanvas")
— mimi

40

몇 시간 전에 같은 문제에 직면했습니다.

".clear ()"메소드는 실제로 캔버스를 지우지 만 (분명히) 객체를 살아 있고 반응 적으로 남겨 둡니다.

"고급 사용법"섹션에서 공식 문서를 주의 깊게 읽으면 다음과 같이 설명 된 ".destroy ()"메소드를 발견했습니다.

"이를 사용하여 생성 된 모든 차트 인스턴스를 제거합니다. 이렇게하면 Chart.js에서 첨부 된 모든 관련 이벤트 리스너와 함께 Chart.js 내의 차트 개체에 저장된 모든 참조가 정리됩니다."

그것은 실제로 그것이 주장하는 것을 수행하고 그것은 나를 위해 잘 작동했습니다, 나는 그것을 시도해 보는 것이 좋습니다.


예를 보여 주시겠습니까? 여러 번 차단을 사용하려고 시도했지만 작동하지 않습니다. 메서드가 존재하지 않는다는 오류가 항상 발생합니다.
— Ben Hoffman

3
(<ChartInstance> this.chart) .destroy ();
— David Dal Busco

2
이것이 바로 anszwer입니다. 향후 참조는 다음을 참조하십시오. stackoverflow.com/questions/40056555/…
— ThePhi

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

1
이 가장 좋은 대안이다
— RafaSashi

잘 했어. 감사합니다
— Manjunath Siddappa

11

이것은 나를 위해 일한 유일한 것입니다.

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

9

여기서도 같은 문제가 발생했습니다. destroy () 및 clear () 메서드를 사용하려고했지만 성공하지 못했습니다.

다음 방법으로 해결했습니다.

HTML :

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

자바 스크립트 :

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

저에게 완벽하게 작동합니다 ... 도움이 되었으면합니다.


5

이것은 나를 위해 아주 잘 작동했습니다.

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

.destroy를 사용 하여 생성 된 모든 차트 인스턴스를 삭제합니다. 이렇게하면 Chart.js에 연결된 모든 관련 이벤트 리스너와 함께 Chart.js 내의 차트 개체에 저장된 모든 참조가 정리됩니다. 캔버스가 새 차트에 다시 사용되기 전에 호출해야합니다.


이 방법은 나를 위해 제대로 작동하며 호버 콜백을 파괴하는 것처럼 보입니다. 탱크가 많이 !!
— 앙투안 Pointeau

4

Chart.js V2.0에서 다음과 같이 차트 데이터를 업데이트 할 수 있습니다.

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

나는 이것이 훨씬 더 나은 솔루션이라는 데 동의합니다. Destroy는 너무 급진적입니다. 우리가 정말로 원하는 것은 "데이터"를 다시 시작하는 것입니다.
— TS

1

CanvasJS를 사용하면 차트 및 다른 모든 항목을 지우는 데 도움이되며 다른 곳에서 처리하기 전에 캔버스 / 차트를 완전히 설정할 수 있습니다.

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

위의 방법 중 어느 것도 작동하지 않았습니다. 이것은 완벽하게 작동했습니다. 감사합니다.
— 초급

1

.destroy ()도 작동하지 않으므로 이것이 내가하는 일입니다. chart_parent div는 캔버스를 표시하려는 곳입니다. 매번 크기를 조정할 캔버스가 필요 하므로이 답변은 위의 답변의 확장입니다.

HTML :

<div class="main_section" > <div id="chart_parent"></div> <div id="legend"></div> </div>

JQuery :

  $('#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>');

1

하나의 새 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


1

이것은 나를 위해 일했습니다. 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;
}`

1

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>

1

우리가 한 것은 새 차트를 초기화하기 전에 미리보기 Chart 인스턴스 (이미 존재하는 경우)를 제거 / 파기 한 다음 새 차트를 만드는 것입니다.

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

도움이 되었기를 바랍니다.


1

아담의 답변 보완

Vanilla 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


1

2020 년 간단한 편집 :

이것은 나를 위해 일했습니다. 창을 소유하여 차트를 글로벌로 변경하십시오 (선언을에서 var myChart로 변경하십시오 window myChart).

차트 변수가 이미 Chart로 초기화되어 있는지 확인하십시오. 그렇다면 동일한 이름으로 다른 변수를 만들 수 있더라도 제거하고 새로 만드십시오. 다음은 코드입니다.

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

작동하기를 바랍니다!


1
매우 감사합니다. 이것은 나를 위해 작동합니다.
— Dante

0

나를 위해 이것은 일했습니다.

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


0

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().


0

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

또는 2D 데이터 세트를 사용하는지 여부에 따라

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

전체 차트 / 데이터 세트를 완전히 파괴하고 모든 것을 재 구축하는 것보다 훨씬 가볍습니다.


0

나를 좋아하는 사람들은 함수를 사용하여 여러 그래픽을 생성하고 블록도 업데이트하고 싶은 경우 .destroy () 함수 만 저에게 효과적이었습니다. . 다음은 도움이 될 수있는 코드 스 니펫입니다.

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 ...
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.