Chartjs条形图显示悬停时的旧数据

时间:2017-03-14 14:38:13

标签: javascript jquery chart.js

我有一个使用chart.js创建的条形图。在页面加载时一切正常,但是当我使用daterangepicker更改时间范围时,会出现毛刺。新数据被引入,但当我将鼠标悬停在它上面时,会显示旧数据。我是javascript的新手,所以我希望得到一些帮助。看起来我需要合并.destroy();不知怎的,但我不知道怎么做。我的代码片段如下:

function loadFTPRChart(startdate, enddate){
var BCData = {
labels: [],
datasets: [
 {
  label: "Pass %",
  backgroundColor: "#536A7F",
  data: [],
  stack: 1
},
{
  label: "Fail %",
  backgroundColor: "#e6e6e6",
  data: [],
  stack: 1
},
{
  label: "Auto %",
  backgroundColor: "#286090",
  data: [],
  stack: 2
},
{
  label: "Manual %",
  backgroundColor: "#f0f0f0",
  data: [],
  stack: 2
}
 ]
};
  $.getJSON( "content/FTPR_AM_Graph_ajax.php", {
    startdate: startdate,
    enddate: enddate,
    location: "M"
})
.done(function( data ) {
    console.log("data", data);
    $.each( data.aaData, function( key, val ) {
      if(val == ""){return true}
      BCData.labels.push("Coater " + val[0]);
      BCData.datasets[0].data.push(parseFloat(val[2]));
      BCData.datasets[1].data.push(parseFloat(100-val[2]));
      BCData.datasets[2].data.push(parseFloat(val[1]));
      BCData.datasets[3].data.push(parseFloat(100-val[1]));
    });

    var option = {   
     responsive:true,
};
console.log("BCData", BCData);


//console.log("PrevData", data);
var ctx = document.getElementById("mybarChart2").getContext("2d");
new Chart(ctx, {
  type: 'groupableBar',
  data: BCData,
  options: {
    scales: {
      yAxes: [{
        ticks: {
          max: 100,
        },
        stacked: true,
      }]
    }
  }
});
});

}


loadFTPRChart($('#reportrange').data().daterangepicker.startDate.format('MM/DD/YYYY'), $('#reportrange').data().daterangepicker.endDate.format('MM/DD/YYYY'));

销毁原始数据的最佳方法是什么,以便在我更改日期范围并将鼠标悬停在新图表上时,旧数据不再闪烁?

由于

11 个答案:

答案 0 :(得分:26)

使用您正在采用的方法(例如,每次日期范围更改时创建一个新的图表对象),然后您必须首先销毁上一个图表,然后创建新图表。

您可以使用.destroy()原型方法执行此操作。这正是API所声明的内容。

  

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

因此,您的代码看起来像这样(请注意我们销毁并重新创建)。

// define a variable to store the chart instance (this must be outside of your function)
var myChart;

function loadFTPRChart(startdate, enddate) {
  var BCData = {
    labels: [],
    datasets: [{
      label: "Pass %",
      backgroundColor: "#536A7F",
      data: [],
      stack: 1
    }, {
      label: "Fail %",
      backgroundColor: "#e6e6e6",
      data: [],
      stack: 1
    }, {
      label: "Auto %",
      backgroundColor: "#286090",
      data: [],
      stack: 2
    }, {
      label: "Manual %",
      backgroundColor: "#f0f0f0",
      data: [],
      stack: 2
    }]
  };

  $.getJSON("content/FTPR_AM_Graph_ajax.php", {
      startdate: startdate,
      enddate: enddate,
      location: "M"
    })
    .done(function(data) {
      console.log("data", data);
      $.each(data.aaData, function(key, val) {
        if (val == "") {
          return true
        }
        BCData.labels.push("Coater " + val[0]);
        BCData.datasets[0].data.push(parseFloat(val[2]));
        BCData.datasets[1].data.push(parseFloat(100 - val[2]));
        BCData.datasets[2].data.push(parseFloat(val[1]));
        BCData.datasets[3].data.push(parseFloat(100 - val[1]));
      });

      var option = {
        responsive: true,
      };
      console.log("BCData", BCData);

      // if the chart is not undefined (e.g. it has been created)
      // then destory the old one so we can create a new one later
      if (myChart) {
        myChart.destroy();
      }

      var ctx = document.getElementById("mybarChart2").getContext("2d");
      myChart = new Chart(ctx, {
        type: 'groupableBar',
        data: BCData,
        options: {
          scales: {
            yAxes: [{
              ticks: {
                max: 100,
              },
              stacked: true,
            }]
          }
        }
      });
    });
}

话虽如此,一遍又一遍地破坏/创造是昂贵的,实际上甚至没有必要。还有另一个名为.update()的原型方法,如果您更改了它的基础数据或标签对象,您可以使用它来重新渲染图表。

这是一个jsfiddle,显示了更改基础数据和标签,然后重新渲染图表的示例。我强烈建议你改用这种方法。

以下是您的代码如何采用这种更好的方法。

// define a variable to store the chart instance (this must be outside of your function)
var myChart;

function loadFTPRChart(startdate, enddate) {
  var BCData = {
    labels: [],
    datasets: [{
      label: "Pass %",
      backgroundColor: "#536A7F",
      data: [],
      stack: 1
    }, {
      label: "Fail %",
      backgroundColor: "#e6e6e6",
      data: [],
      stack: 1
    }, {
      label: "Auto %",
      backgroundColor: "#286090",
      data: [],
      stack: 2
    }, {
      label: "Manual %",
      backgroundColor: "#f0f0f0",
      data: [],
      stack: 2
    }]
  };

  $.getJSON("content/FTPR_AM_Graph_ajax.php", {
      startdate: startdate,
      enddate: enddate,
      location: "M"
    })
    .done(function(data) {
      console.log("data", data);
      $.each(data.aaData, function(key, val) {
        if (val == "") {
          return true
        }
        BCData.labels.push("Coater " + val[0]);
        BCData.datasets[0].data.push(parseFloat(val[2]));
        BCData.datasets[1].data.push(parseFloat(100 - val[2]));
        BCData.datasets[2].data.push(parseFloat(val[1]));
        BCData.datasets[3].data.push(parseFloat(100 - val[1]));
      });

      var option = {
        responsive: true,
      };
      console.log("BCData", BCData);

      // if the chart is not undefined (e.g. it has been created)
      // then just update the underlying labels and data for each
      // dataset and re-render the chart
      if (myChart) {
        myChart.data.labels = BCData.labels;
        myChart.data.datasets[0].data = BCData.datasets[0].data;
        myChart.data.datasets[1].data = BCData.datasets[1].data;
        myChart.data.datasets[2].data = BCData.datasets[2].data;
        myChart.data.datasets[3].data = BCData.datasets[3].data;
        myChart.update();
      } else {
        // otherwise, this is the first time we are loading so create the chart
        var ctx = document.getElementById("mybarChart2").getContext("2d");
        myChart = new Chart(ctx, {
          type: 'groupableBar',
          data: BCData,
          options: {
            scales: {
              yAxes: [{
                ticks: {
                  max: 100,
                },
                stacked: true,
              }]
            }
          }
        });
      }
    });
}

答案 1 :(得分:4)

它将帮助您...

检查 MyChart 是否已经配置,如果存在,请使用 destroy()清除;方法,并将新配置绑定到画布。

示例代码。

if (window.MyChart != undefined)
{
    window.MyChart.destroy();
}
window.MyChart = new Chart(ctx, MyChartconfig);

答案 2 :(得分:3)

这是我发现的chartjs技巧

var ctxLine = document.getElementById("line-chart").getContext("2d");
if(window.bar != undefined) 
window.bar.destroy(); 
window.bar = new Chart(ctxLine, {});

https://therichpost.com/solved-hovering-chartjs-bar-chart-showing-old-data

答案 3 :(得分:2)

stackoverflowing了很多小时后,我发现了一个简单的解决方案,无需进行太多更改... 只需在选项部分添加此行

events:[]

在“选项”部分中,它是一种摆脱悬停时显示旧数据的Chartjs条形图的快速解决方案

如果您还需要悬停事件,则尝试重新初始化或重新渲染画布,并确定条件是否可以解决

答案 4 :(得分:1)

我发现了问题,我的解决方案是先从html中删除它们,然后再加载新图表然后添加画布。

HTML

 $('#chart').empty();
    
$('#chart').html('<canvas id="survey_result"  width="400" height="200"></canvas>'); // then load chart.
    
var ctx = document.getElementById("survey_result");
    <div id="chart" class="display>
    </div>

答案 5 :(得分:1)

有一个简单的解决方案,可以在JS本身完成。

让我们说你的html有类似下面的内容

<div id="chartContainer">
 <canvas id="mybarChart2"></canvas>
</div>

然后在您的脚本中,您可以在更新数据之前添加以下代码行。

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

这解决了我的问题。

答案 6 :(得分:0)

chartjs.org提供的示例代码表明,它们不会破坏()图表并创建一个新图表。相反,他们弹出()图表中的现有数据,并将新的数据集推送()到图表,然后更新()图表。

此代码来自chartjs.org网站,该网站通过POP()从图表中删除了数据集。

    document.getElementById('removeDataset').addEventListener('click', function() {
        horizontalBarChartData.datasets.pop();
        window.myHorizontalBar.update();
    });

此代码用于通过PUSH()将数据集添加到图表中:

    document.getElementById('addDataset').addEventListener('click', function() {
        var colorName = colorNames[horizontalBarChartData.datasets.length % colorNames.length];
        var dsColor = window.chartColors[colorName];
        var newDataset = {
            label: 'Dataset ' + (horizontalBarChartData.datasets.length + 1),
            backgroundColor: color(dsColor).alpha(0.5).rgbString(),
            borderColor: dsColor,
            data: []
        };

        for (var index = 0; index < horizontalBarChartData.labels.length; ++index) {
            newDataset.data.push(randomScalingFactor());
        }

        horizontalBarChartData.datasets.push(newDataset);
        window.myHorizontalBar.update();
    });

这两个代码块的最后一步是更新图表。

通常来说,有必要从图表中弹出要删除的数据,然后推送新数据,最后更新图表。因此,悬停时将不会显示以前的数据。

答案 7 :(得分:0)

我知道这已经很老了,但是其中大多数在我的情况下不起作用,所以我要发布对我有用的东西。

我有两个图表展示了这种行为,一个z堆积的条形图和一个饼图。我尝试了这些都无济于事:

  • myChart.destroy():这可以更改值,但是由于某些原因,还影响了我的图表的大小和显示值
  • options: { events: [] }:如该帖子所述,这删除了我仍然想要的所有悬停工具提示
  • innerHTML:我不知道这是否是chartjs的新功能,但是除""
  • 之外,我的任何图表都没有拥有innerHTML属性
  • myChart.datasets.pop():这是我解决方案的精髓,但是在大多数情况下,我拥有多个数据集,因此我将它们全部删除:

  if (myChart !== undefined) {
    while (myChart.data.datasets.length > 0) {
      myChart.data.datasets.pop();
    }
  }

我以前还使用创建图表和组织数据的功能创建了var myChart。将变量声明移到函数外并在函数内实现以上操作后,它们就像一个吊饰一样工作!

答案 8 :(得分:0)

对我有用的方法(也许效果不佳,但这对我来说不是什么大问题,因为每次访问只能进行几次)-销毁并重新创建整个canvas对象(使用JQuery)。

$("#canvasID").remove();
$("<canvas>").attr({
    id: "canvasID"
}).appendTo("#canvasParent");

答案 9 :(得分:0)

我根本无法使用“destroy()”。我挣扎。我最终完全删除了元素,然后在每次更新数据时重新创建。

        if(document.getElementById(chartID)) {
            document.getElementById(chartID).remove();
        }
        

        var canvasParent;
        // I had 2 charts, so a ternary to select the right element
        chartID == 'fleet-fuel-chartComp1' ? canvasParent = document.getElementById('canvas-node1') : canvasParent = document.getElementById('canvas-node2');
        
        var canvas = document.createElement('canvas');
        canvas.id = chartID;
        canvasParent.appendChild(canvas);

        var ffc = document.getElementById(chartID);

答案 10 :(得分:0)

将 myChart 声明为全局变量

let mychart;

在图创建之前只写

function pieChart(pdata) {
        // destroy previous created graph
        if (myChart) {
            myChart.destroy()
        }
        let ctx = document.getElementById("pie-chart").getContext('2d');
         myChart = new Chart(ctx, {

            type: 'doughnut',
            data: {
                labels: ['Count'],
                datasets: [{
                    backgroundColor: [
                        "#2ecc71",
                    ],
                    data: [pdata],

                }]
            },
            
        });
    }

我们为什么要添加这个?因为,如果我们第一次创建任何图形 mychart 创建一个对象,在这种情况下,当我们对其进行 randing 时,它不会发生变化。这就是为什么我们需要销毁以前的对象并为更新的可视化创建新对象。