DRY使用d3.layout.stack()堆叠多个指标的方法

时间:2012-08-19 07:48:01

标签: javascript d3.js

我正在使用d3.js Streamgraph来显示销售额。然后,我有一个转变,以显示同期的利润。数据如下所示:

var data = [{
    "name": "apples",
    "sales": [{
        "x": 0,
        "y": 941
    }, {
        "x": 1,
        "y": 490
    }],
    "profit": [{
        "x": 0,
        "y": 6
    }, {
        "x": 1,
        "y": 3
    }]
}, {
    "name": "oranges",
    "sales": [{
        "x": 0,
        "y": 344
    }, {
        "x": 1,
        "y": 425
    }],
    "profit": [{
        "x": 0,
        "y": 3
    }, {
        "x": 1,
        "y": 2
    }]
}];

它有效,但我目前正在以一种有点火腿的方式生成堆叠数据,应用stack.values两次:

var stack_sales = d3.layout.stack()
    .offset("wiggle")
    .values(function(d) { return d.sales; });

var stack_profit = d3.layout.stack()
    .offset("wiggle")
    .values(function(d) { return d.profit; });

stack_sales(data);
stack_profit(data);

我一直在进入JavaScript Patterns,但看不到DRY这样做的方法。你能帮忙吗?

1 个答案:

答案 0 :(得分:2)

一种选择是动态定义值函数:

var stack = d3.layout.stack().offset("wiggle");
["sales", "profit"].forEach(function(metric) {
  stack.values(function(d) { return d[metric]; })(data);
});

另一个选择是转置您的数据,以便指标位于外部,系列内部:

var metrics = [
  {
    "name": "sales",
    "series": [
      {
        "name": "apples",
        "values": [
          {"x": 0, "y": 941}, 
          {"x": 1, "y": 490}
        ]
      }, 
      {
        "name": "oranges",
        "values": [
          {"x": 0, "y": 344}, 
          {"x": 1, "y": 425}
        ]
      }
    ]
  }, {
    "name": "profits",
    "series": [
      {
        "name": "apples",
        "values": [
          {"x": 0, "y": 0}, 
          {"x": 1, "y": 6}
        ]
      }, 
      {
        "name": "oranges",
        "values": [
          {"x": 0, "y": 1}, 
          {"x": 1, "y": 3}
        ]
      }
    ]
  }
];

然后您可以静态访问这些值:

var stack = d3.layout.stack()
    .offset("wiggle")
    .values(function(d) { return d.values; });

metrics.forEach(function(metric) {
  stack(metric.series);
});