使用d3.relayout.stack()堆栈多个度量的DRY方式

DRY way to stack multiple metrics with d3.layout.stack()

本文关键字:度量 DRY 方式 堆栈 relayout d3 stack 使用      更新时间:2023-09-26

我使用d3.js流图来显示一段时间内的销售额。然后,我有一个过渡,显示利润在同一时期。数据如下:

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
    }]
}];

它是有效的,但我目前正在以一种有点笨拙的方式生成堆叠的数据,两次应用堆叠值:

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模式,但看不到干的方法。你能帮忙吗?

一个选项是动态定义值函数:

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