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

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

.update( )

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

.addData( valuesArray, label )

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

.removeData( )

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

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

【问题讨论】:

    标签: javascript chart.js


    【解决方案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,outputjsbin.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" height="your-height" width="your-width"></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();
                            

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2018-07-18
                              • 1970-01-01
                              • 1970-01-01
                              • 2018-11-10
                              • 1970-01-01
                              • 1970-01-01
                              相关资源
                              最近更新 更多