重新加载图表后,nvd3在stateChange上传递错误事件(单击图例时)

时间:2014-04-11 14:14:01

标签: javascript d3.js charts nvd3.js

我有一张nvd3多栏图表(但饼图会出现同样的问题)。

我希望在用户启用或禁用系列时保存图例的状态,方法是在图例中单击它。所以我正在听 stateChange 事件。

在以下示例代码中,有两个系列。当用户点击 series1 以禁用它时,控制台应该记录:

New State: {"disabled":[true,false]}

使用服务器中的新数据刷新图表后会出现问题(在下面的代码中由 setInterval 模拟)。第一次刷新后,我总是收到错误的事件,即 已禁用属性的值被搞砸了

也许我刷新图表的方式是错误的?

示例代码:

  var initialData = [
      { key: 'series1', values: [
            { x: 0, y: 10},
            { x: 1, y: 44}
          ]},
      { key: 'series2', values: [
            { x: 0, y: 25},
            { x: 1, y: 11}
          ]}
    ];

  var chart;
  nv.addGraph(function() {

      chart = nv.models.multiBarChart()
        .delay(0);

      d3.select('#chart1 svg')
          .datum(initialData)
          .call(chart);

      nv.utils.windowResize(chart.update);

      chart.dispatch.on('stateChange', function(e) {
        nv.log('New State:', JSON.stringify(e));
      });


      setInterval(function ()
      {
        var newDataFromServer = [
          { key: 'series1', values: [
                { x: 0, y: Math.floor((Math.random()*100)+1)},
                { x: 1, y: Math.floor((Math.random()*100)+1)}
              ]},
          { key: 'series2', values: [
                { x: 0, y: Math.floor((Math.random()*100)+1)},
                { x: 1, y: Math.floor((Math.random()*100)+1)}
              ]}
        ];

        d3.select('#chart1 svg')
          .datum(newDataFromServer)
          .call(chart);

        nv.utils.windowResize(chart.update);

      }, 5000);

      return chart;
  });

1 个答案:

答案 0 :(得分:1)

我找到了一个有效的解决方案。我没有时间进一步调查,但在以下代码中( nvd3 / legend.js ):

  .on('click', function(d,i) {
    dispatch.legendClick(d,i);
    if (updateState) {
       if (radioButtonMode) {
            // etc ...
       }
       else {
            // Note: this 'd' doesn't belong to the 'data' array in the current scope
           d.disabled = !d.disabled;
           // etc ...
       }
       dispatch.stateChange({
          // The old data is notified as event
          disabled: data.map(function(d) { return !!d.disabled })
       });
    }
  })

当行为不端时(即第一次更新后), d对象不属于此范围内的数据数组(假设去做)。我猜这个数据总是指向初始数据数组。

作为更新图表的解决方法,我获取了初​​始数组并就地更新了它:

// Get reference to data array object
var chartDatum = d3.select('#chart1 svg')
                        .datum();
// Clear array and copy new data into it                        
chartDatum.length = 0;
angular.extend(chartDatum, newDataFromServer); // Or jQuery extend, or equivalent
chart.update();