chart.js 加载全新数据

Posted

技术标签:

【中文标题】chart.js 加载全新数据【英文标题】:chart.js load totally new data 【发布时间】:2014-09-07 06:32:24 【问题描述】:

The API for chart.js 允许编辑加载到其中的数据集的点,例如:

.update( )

在 Chart 实例上调用 update() 将重新渲染图表 任何更新的值,允许您编辑多个值 现有点,然后在一个动画渲染循环中渲染它们。

.addData( valuesArray, label )

在您的 Chart 实例上调用 addData(valuesArray, label) 传递一个 每个数据集的值数组,以及这些点的标签。

.removeData( )

在您的 Chart 实例上调用 removeData() 将删除第一个 图表上所有数据集的值。

所有这些都很棒,但我不知道如何加载一个全新的数据集,消除旧的。文档似乎没有涵盖这一点。

【问题讨论】:

【参考方案1】:

我遇到了很大的问题

首先我尝试了.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'); // why use jQuery?
  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);
;

【讨论】:

这个答案有效,但我发现 destroy 在最新版本中也有效。在这篇文章中推荐 - github.com/nnnick/Chart.js/issues/559 这将有助于清空图形容器 div 以删除旧的 iframe $('#results-graph').remove(); $('#graph-container').empty(); $('#graph-container').append('');【参考方案2】:

你需要销毁:

myLineChart.destroy();

然后重新初始化图表:

var ctx = document.getElementById("myChartLine").getContext("2d");
myLineChart = new Chart(ctx).Line(data, options);

【讨论】:

就这样使用 if(window.myLine) window.myLine.destroy(); OR if(myLineChart) myLineChart.destroy(); 可以确认销毁然后重新初始化不会导致任何闪烁,并且看起来数据点是动态更新的【参考方案3】:

使用 Chart.js V2.0,您可以执行以下操作:

websiteChart.config.data = some_new_data;
websiteChart.update();

【讨论】:

正是操作所要求的。 当我做chart.config.data = newData 时,我有这个错误:TypeError: undefined is not an object (evaluating 'i.data.datasets.length') 有人有同样的问题吗?【参考方案4】:

这是一个旧线程,但在当前版本中(截至 2017 年 2 月 1 日),很容易替换在 chart.js 上绘制的数据集:

假设您的新 x 轴值在数组 x 中,y 轴值在数组 y 中, 您可以使用下面的代码来更新图表。

var x = [1,2,3];
var y = [1,1,1];

chart.data.datasets[0].data = y;
chart.data.labels = x;

chart.update();

【讨论】:

非常感谢,伙计!浪费了一整天。终于偶然发现了你的答案。谢谢。 这对我很有帮助。即使只是使用 [] 设置一个空数据集,然后执行新的“推送”也可以达到目的。【参考方案5】:

ChartJS 2.6 支持数据引用替换(请参阅 update(config) 文档中的Note)。所以当你有你的图表时,你基本上可以这样做:

myChart.data.labels = ['1am', '2am', '3am', '4am'];
myChart.data.datasets[0].data = [0, 12, 35, 36];
myChart.update();

它不会执行您通过添加点获得的动画,但图表上的现有点将被动画化。

【讨论】:

【参考方案6】:

我对此的解决方案非常简单。 (版本 1.X)

getDataSet:function(valuesArr1,valuesArr2)
        var dataset = [];
        var arr1 = 
            label: " (myvalues1)",
            fillColor: "rgba(0, 138, 212,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(0, 138, 212,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: valuesArr1
        ;
        var arr2 = 
            label: " (myvalues2)",
            fillColor: "rgba(255, 174, 087,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(255, 174, 087,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: valuesArr2
        ;
        /*Example conditions*/
        if(condition 1)
          dataset.push(arr1);
        
        if(condition 2)
          dataset.push(arr1);
          dataset.push(arr2);
        

        return dataset;
    

var data = 
    labels: mylabelone,
    datasets: getDataSet()
;
if(myBarChart != null) // i initialize myBarChart var with null
    myBarChart.destroy(); // if not null call destroy
    myBarChart = new Chart(ctxmini).Bar(data, options);//render it again ...

没有闪烁或问题。 getDataSet 是一个控制我需要呈现什么数据集的函数

【讨论】:

能不能把getDataSet()的sn-p代码也加进去? 添加了 getDataSet() 示例【参考方案7】:

我在这里回答了这个问题,请参阅How to clear a chart from a canvas so that hover events cannot be triggered?

但这里是解决方案:

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

【讨论】:

【参考方案8】:

根据文档,clear() 清除画布。将其视为 Paint 中的橡皮擦工具。它与图表实例中当前加载的数据无关。

销毁实例并创建一个新实例是浪费。相反,请使用 API 方法 removeData()addData()。这些将在图表实例中添加/删除单个段。所以如果你想加载全新的数据,只需循环一个图表数据数组,然后调用removeData(index)(数组索引应该对应于当前段索引)。然后,使用addData(index) 用新数据填充它。我建议包装这两种循环数据的方法,因为它们期望单个段索引。我使用resetChartupdateChart在继续之前,请务必查看 Chart.js 最新版本和文档。他们可能已经添加了完全替换数据的新方法

【讨论】:

我喜欢你的回答,它与我在网上阅读的信息一致。如果您能够展示和举例,那将非常有帮助。我在网上看到的两个类似的例子是:jsbin.com/yitep/5/edit?html,js,output和jsbin.com/yitep/4/edit?html,js,output 唯一的问题是,如果您必须用本质上完全不同的数据集替换图表数据,更新图表会变得非常麻烦且超级慢。对于初学者,我还没有找到更新现有 x 轴 标签 的方法。在这种情况下,销毁并重新实例化整个图表是唯一真正的解决方案。 不幸的是,我只处理了一个不太复杂的甜甜圈图。您是否查看了最新的 API?【参考方案9】:

我遇到了同样的问题,我在一个页面上有 6 个饼图,可以同时更新。我正在使用以下函数来重置图表数据。

// sets chart segment data for previously rendered charts
function _resetChartData(chart, new_segments) 
    // remove all the segments
    while (chart.segments.length) 
        chart.removeData();
    ;

    // add the new data fresh
    new_segments.forEach (function (segment, index) 
        chart.addData(segment, index);
    );
;

// when I want to reset my data I call
_resetChartData(some_chart, new_data_segments);
some_chart.update();

【讨论】:

虽然这可行,但我发现与完全重新创建图表相比,它慢得多(由于添加每个点时的动画)。【参考方案10】:

不必破坏图表。试试这个

function removeData(chart) 

        let total = chart.data.labels.length;

        while (total >= 0) 
            chart.data.labels.pop();
            chart.data.datasets[0].data.pop();
            total--;
        

        chart.update();
    

【讨论】:

【参考方案11】:

我尝试了neaumusic的解决方案,但后来发现only problem with destroy is the scope。

var chart;

function renderGraph() 
    // Destroy old graph
    if (chart) 
        chart.destroy();
    

    // Render chart
    chart = new Chart(
        document.getElementById(idChartMainWrapperCanvas),
        chartOptions
    );

将我的图表变量移到函数范围之外,让它为我工作。

【讨论】:

【参考方案12】:

以上答案都没有以非常简洁的方式以最少的代码帮助我的特殊情况。我需要删除所有数据集,然后循环以动态添加几个数据集。所以这个片段是为那些一直到页面底部而没有找到答案的人准备的:)

注意:确保在将所有新数据加载到数据集对象后调用 chart.update()。希望这可以帮助某人

function removeData(chart) 
   chart.data.datasets.length = 0;


function addData(chart, data) 
  chart.data.datasets.push(data);

【讨论】:

【参考方案13】:

您需要清理旧数据。无需重新初始化:

for (i in myChartLine.datasets[0].points)
    myChartLine.removeData();

【讨论】:

【参考方案14】:

请了解 Chart.js(此处为第 2 版)的工作原理,并针对您想要的任何属性进行操作:


1.请假设您的 HTML 中有如下条形图:
<canvas id="your-chart-id"  ></canvas>

2.请假设您有一个第一次填充图表的 javascript 代码(例如在加载页面时):

var ctx = document.getElementById('your-chart-id').getContext('2d');
var chartInstance = new Chart(ctx, 
    type: 'bar',
    data: 
        labels: your-lables-array,
        datasets: [
            data: your-data-array,
            /*you can create random colors dynamically by ColorHash library [https://github.com/zenozeng/color-hash]*/
            backgroundColor: your-lables-array.map(function (item) 
                return colorHash.hex(item);
            )
        ]
    ,
    options: 
        maintainAspectRatio: false,
        scales: 
            yAxes: [  ticks: beginAtZero: true  ]
        ,
        title: display: true, fontSize: 16, text: 'chart title',
        legend: display: false
    
);

请假设您想要完全更新您的数据集。 这很简单。请查看上面的代码,看看从图表变量到数据的路径如何,然后按照以下路径:

选择chartInstance var. 然后在chartInstance中选择data node。 然后在data node中选择datasets node。(注意:As 你可以看到,datasets node 是一个数组。所以你必须 指定你想要的这个数组的哪个元素。这里我们只有一个 datasets node 中的元素。所以我们使用datasets[0] 所以选择datasets[0] 然后在datasets[0]里面选择data node

此步骤为您提供chartInstance.data.datasets[0].data,您可以设置新数据并更新图表:

chartInstance.data.datasets[0].data = NEW-your-data-array
//finally update chart var:
chartInstance.update();


注意: 按照上面的算法,你可以简单的实现到你想要的每个节点

【讨论】:

【参考方案15】:

如果有人正在寻找如何在 React 中执行此操作。对于折线图,假设您在图表周围有一个包装器组件:

(假设您使用的是 v2。您不需要使用 react-chartjs。这是使用来自 npm 的普通 chart.js 包。)

propTypes: 
  data: React.PropTypes.shape(
    datasets: React.PropTypes.arrayOf(
      React.PropTypes.shape(

      )
    ),
    labels: React.PropTypes.array.isRequired
  ).isRequired
,
componentDidMount () 
  let chartCanvas = this.refs.chart;

  let myChart = new Chart(chartCanvas, 
    type: 'line',
    data: this.props.data,
    options: 
      ...
    
  );

  this.setState(chart: myChart);
,
componentDidUpdate () 
    let chart = this.state.chart;
    let data = this.props.data;

    data.datasets.forEach((dataset, i) => chart.data.datasets[i].data = dataset.data);

    chart.data.labels = data.labels;
    chart.update();
,
render () 
  return (
    <canvas ref='chart' height='400' width='600'></canvas>
  );

componentDidUpdate 功能允许您更新、添加或删除this.props.data 中的任何数据。

【讨论】:

【参考方案16】:

到目前为止,我能为自己找到的唯一解决方案是从头开始重新初始化图表:

var myLineChart = new Chart(ctx).Line(data, options);

然而,这对我来说似乎有点做作。任何人有更好、更标准的解决方案吗?

【讨论】:

这对我来说非常有用,除了你需要先做 myLineChart.destroy() 来摆脱旧的,否则你会在重绘时闪烁。【参考方案17】:

我也遇到了很多麻烦。我在单独的数组中有数据和标签,然后我重新初始化图表数据。我添加了 line.destroy();如上所述,这已经成功了

var ctx = document.getElementById("canvas").getContext("2d");
if(window.myLine)
	window.myLine.destroy();

window.myLine = new Chart(ctx).Line(lineChartData, 
  etc
  etc

【讨论】:

【参考方案18】:

有一种方法可以在不清除画布或重新开始的情况下执行此操作,但您必须手动处理图表的创建,以便更新时数据的格式相同。

这是我的做法。

    var ctx = document.getElementById("myChart").getContext("2d");
    if (chartExists) 
        for (i=0;i<10;i++)
            myNewChart.scale.xLabels[i]=dbLabels[i]; 
            myNewChart.datasets[0].bars[i].value=dbOnAir[i];
        
        myNewChart.update();
      else
          console.log('chart doesnt exist');
          myNewChart = new Chart(ctx).Bar(dataNew);
          myNewChart.removeData();
          for (i=0;i<10;i++)
              myNewChart.addData([10],dbLabels[i]);
          
          for (i=0;i<10;i++)      
              myNewChart.datasets[0].bars[i].value=dbOnAir[i];
          
          myNewChart.update();
          chartExists=true;
        

我基本上将创建时加载的数据废弃,然后用添加数据方法进行改造。这意味着我可以访问所有点。每当我尝试访问由以下创建的数据结构时:

Chart(ctx).Bar(dataNew);

命令,我无法访问我需要的内容。这意味着您可以按照创建它们的相同方式更改所有数据点,并且还可以调用 update() 而无需完全从头开始制作动画。

【讨论】:

【参考方案19】:

图表 JS 2.0

刚刚设置 chart.data.labels = [];

例如:

function addData(chart, label, data) 
    chart.data.labels.push(label);
    chart.data.datasets.forEach((dataset) => 
       dataset.data.push(data);
    );
    chart.update();


$chart.data.labels = [];

$.each(res.grouped, function(i,o) 
   addData($chart, o.age, o.count);
);
$chart.update();

【讨论】:

【参考方案20】:

创建图表对象时,您需要将实例保存在变量中。

var currentChart = new Chart(ctx, ...);

在加载新数据之前,您需要销毁它:

currentChart.destroy();

【讨论】:

【参考方案21】:

首先,让变量记住图表的一个实例。

             let yourChart = new Chart(ctxBar, 
                    type: 'bar',
                    data: 
                        labels: labels,
                        datasets: datasets
                    ,
                );

其次,我最苦恼的事情是在更新图表之前以正确的格式获取数据结构。所以看了图表js对象的data键结构后:

  data: 
        labels: ['Jan', 'Feb'],
        datasets: [
            label: 'Net sales',
            data: data
        , 
            label: 'Cost of goods sold',
            data: data
        , 
            label: 'Gross margin',
            data: data
        ]
    

请注意,data 键值是一个由两个键组成的对象,labelsdatasetslabelskey'的值是一个数组,而datasetskey'的值也是一个以对象为值的数组。

因此,我使用的图表实例中的remove 标签和数据集:

yourChart.data.labels = [];
yourChart.data.datasets = [];
yourChart.update();

add 标签和数据集到我使用的图表实例:

yourChart.data.labels = ['label 1', 'label 2'];
yourChart.data.datasets = [
                label: 'column lables',
                data: [450, 50],
                backgroundColor: ["#dc3545", "#ffb759"]
            ];
yourChart.update();

准备服务器端 标签和数据集值可以在服务器端按如下方式准备(在我的情况下为 php):

$datajs = function ($data, $bg_colour) // function emulating chart js datasets key value structure
        
            return [
                'data' => $data,
                'backgroundColor' => $bg_colour
            ];
        ;
$datasets = [];
$labels = ['label 1', 'label 2'];
$datasets[] = $datajs([42,10], ["#dc3545", "#ffb759"]);
$datasets[] = $datajs([100,5], ["#dc3545", "#ffb759"]);

仅从数据集中的数据键值替换数据(我没有测试过)

yourChart.data.datasets.forEach((dataset) => 
    dataset.data = [];
);
yourChart.update();
// if you have an array of arrays
let array = [[42,20],[58,68],[78,1]];
let length = yourChart.data.datasets.length;
for (let i = 0; i < array.length; i++) 
    const element = array[i];
    if (i < length) 
        yourChart.data.datasets[i].data = element;
     else 
        yourChart.data.datasets[] = data: element;
    

yourChart.update();

【讨论】:

以上是关于chart.js 加载全新数据的主要内容,如果未能解决你的问题,请参考以下文章

使用require.js发出加载chart.js缩放插件的问题

chart.js简单的图标绘制工具

chart.js 折线图不显示超过图表中某个点的线

Chart Js显示鼠标悬停时的旧数据

使用ASP.NET中的Chart.js在ASP.NETVisual数据中使用Chart.js的可视化数据

chart.js 3 和时间轴显示错误的日期数据