Як очистити діаграму з полотна, щоб не можна було викликати події наведення?


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
Чувак, це якраз та проблема. Метод "знищити ()" не працює, і це мене дратує.
неаумузичний

Чи можу я запитати, як ви отримуєте доступ до об’єкта діаграми? У мене виникають ті ж проблеми, я створюю діаграму, а потім при натисканні кнопки мені потрібно знищити її, але вона знаходиться в зовсім іншій функції, і я не можу знайти спосіб доступу до об'єкта діаграми через полотно або контекст об’єкти.
Метт Вільямс

Відкрита помилка для цієї проблеми, дивіться її тут. github.com/jtblin/angular-chart.js/isissue/187
MDT

Була ця проблема. Рішення про створення / відновлення stackoverflow.com/a/51882403/1181367
Кріс

Відповіді:


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, опублікуйте це тут. Цікаво, чи зруйнується знищення чи ми використовуємо його неправильно.
TheLettuceMaster

2
Приємно! Дякую! Я щойно додав $ ('# Результат-графік'). Remove (); $ ('# graph-container'). append ('<canvas id = "Результат-графік"> <canvas>'); перед створенням діаграми
Ігнасіо

.destroy () повинен працювати добре. Якщо це не так, після виклику .destroy () намалювати новий графік, використовуйте setTimeout ()
Sumeet Kale

це єдине рішення, яке працювало для мене велике спасибі, але за ширину та висоту, якщо ви їх вже встановили, слід повернути їх до того самого значення у функції скидання
Sandy Elkassar

2
знищити () не вдалося для мене з графіком 2.8.0, але ваше рішення просто працювало! У моєму випадку я використав тільки $('#results-graph').remove(); $('#graph-container').append('<canvas id="results-graph"><canvas>');передnew Chart(document.getElementById("myCanvas")
Mimi

40

Я зіткнувся з тією ж проблемою кілька годин тому.

Метод ".clear ()" насправді очищає полотно, але (очевидно) він залишає об'єкт живим і реактивним.

Уважно прочитавши офіційну документацію , у розділі «Розширене використання» я помітив метод «.destroy ()», описаний так:

"Використовуйте це, щоб знищити будь-які створені екземпляри діаграми. Це очистить будь-які посилання, збережені на об'єкт діаграми в Chart.js, а також будь-які пов'язані слухачі подій, приєднані Chart.js."

Він насправді робить те, що він вимагає, і для мене це спрацювало чудово, я пропоную вам спробувати.


Чи можете ви показати приклад? Я кілька разів намагався використовувати блокування, і це ніколи не працює. Я завжди отримую помилку, що методу не існує.
Бен Хоффман

3
(<ChartInstance> this.chart) .destroy ();
Девід Даль Буско

2
Це правильний відповідь. Для довідки в майбутньому, см: 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

Хороший. Спасибі
Манджунат Сіддаппа

11

Це єдине, що працювало для мене:

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

9

У мене була така сама проблема ... Я намагався використовувати метод знищення () та 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);

Це прекрасно працює для мене ... Я сподіваюся, що це допомагає.


5

Це дуже добре спрацювало для мене

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

Використовуйте .destroy для знищення будь-яких створених екземплярів діаграми. Це очистить будь-які посилання, що зберігаються на об'єкті діаграми в Chart.js, а також будь-які пов'язані слухачі подій, приєднані Chart.js. Це потрібно викликати перед повторним використанням полотна для нової діаграми.


Цей спосіб працює належним чином для мене, схоже, він руйнує зворотні дзвінки. Танки так сильно !!
Антуан Пуанто

4

Ми можемо оновити дані діаграми в Chart.js V2.0 наступним чином:

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

Я погоджуюсь з цим як з набагато кращим рішенням - Знищення буває надто радикальним, коли все, що ми дійсно хочемо, - це просто перезапустити "дані".
TS

1

Використовуючи CanvasJS, це працює для мене з очищенням діаграми та всього іншого, можливо, може працювати і для вас, надаючи вам встановити своє полотно / діаграму повністю перед кожною обробкою в іншому місці:

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

для мене не працював не з перерахованих вище методів. Це спрацювало чудово. Дуже дякую.
початківець

1

Я не міг змусити .destroy () працювати, так що це те, що я роблю. Діва діаграми char_parent - це те, де я хочу відобразити полотно. Мені потрібно полотно для зміни розміру кожного разу, тому ця відповідь є розширенням вищезгаданого.

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.

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

Це працювало для мене. Додайте дзвінок до clearChart у верхній частині оновленняChart ()

`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

Якщо ви використовуєте chart.js в проекті Angular з Typescript, ви можете спробувати наступне;

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 preview, якщо такий вже існує, то створити новий графік, наприклад

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

Сподіваюся, це допомагає.


1

Доповнення відповіді Адама

З ванільним 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
Дуже дякую. Це працює для мене.
Данте

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

Оскільки знищення типу знищує "все", дешеве і просте рішення, коли все, що вам дуже хочеться, - це просто "скинути дані". Скидання наборів даних у порожній масив також буде добре працювати. Отже, якщо у вас є набір даних із мітками та віссю з кожної сторони:

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 (), я хотів би зробити .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 ...
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.