如何从D3中的现有面积图制作堆积面积图

时间:2018-09-16 14:19:05

标签: javascript d3.js

我需要获取现有的面积图并将其转换为堆叠的面积图。我看过D3 API和堆积面积图的其他几个示例,但似乎无法弄清楚哪里出了问题。

API(d3.stack)看起来很简单明了,但我显然缺少一些东西。

任何帮助将不胜感激。

这是现有(工作)区域图的代码:

var margin = { top: 20, right: 20, bottom: 30, left: 30 };
var width = 400 - margin.left - margin.right;
var height = 250 - margin.top - margin.bottom;

var svg = d3.select('#chart')
    .append('svg')
    .attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom)
    .append('g')
       .attr('transform', `translate(${margin.left}, ${margin.top})`);

d3.json('data.json', function (err, data) {
    var data = data.employees;

    var parseTime = d3.timeParse('%Y/%m/%d');

    data.forEach(name => {
        name.values.forEach(d => {
            d.date = parseTime(d.date);
            d.volume = d.volume;
        });
    });
    var xScale = d3.scaleTime()
        .domain([
            d3.min(data, nm => d3.min(nm.values, d => d.date)),
            d3.max(data, nm => d3.max(nm.values, d => d.date))
        ])
        .range([0, width])

    var yScale = d3.scaleLinear()
        .domain([
            d3.min(data, nm => d3.min(nm.values, d => d.volume)),
            d3.max(data, nm => d3.max(nm.values, d => d.volume))
        ])
        .range([height, 0])

    var area = d3.area()
        .x(d => xScale(d.date))
        .y0(yScale(yScale.domain()[0]))
        .y1(d => yScale(d.volume))
        .curve(d3.curveCatmullRom);

   //var stack = d3.stack()
     //   .keys(["Employee1", "Employee2"])     
     //   .order(d3.stackOrderNone)
     //   .offset(d3.stackOffsetNone);

     //   var stackAttempt = stack(data);
     //   console.log(stackAttempt);

    svg.selectAll('.area')
        //.data(stackAttempt)
        .data(data)
        .enter()
        .append('path')
        .attr('class', 'area')
        .attr('d', d => area(d.values))
        .style('stroke', (d, i) => ['#22556E', '#6DB3BF'][i])
        .style('stroke-width', 2)
        .style('fill', (d, i) => ['#22556E', '#6DB3BF'][i])
        .style('fill-opacity', 0.3);

    svg.append('g')
        .attr('transform', `translate(0, ${height})`)
        .attr("class", "axisSteel")
        .style('stroke-width', 3)
        .call(d3.axisBottom(xScale).ticks(10));

    svg.append('g')
        .attr("class", "axisSteel")
        .style('stroke-width', 3)
        .call(d3.axisLeft(yScale))

})

使用这种JSON格式:

{
"employees": [
        {
            "name": "Employee1",
            "values": [
                {
                "volume": 17,
                "date": "2018/09/10"
                },{
                "volume": 20,
                "date": "2018/09/11"
                }
            ]
        },
        {
            "name": "Employee2",
            "values": [
                {
                "volume": 10,
                "date": "2018/09/10"
                },{
                "volume": 29,
                "date": "2018/08/11"
                }
            ]
        },
}

1 个答案:

答案 0 :(得分:0)

问题是您的输入数据。

d3.stack不喜欢预先嵌套的数据,d3的大多数起始数据都是这样的平坦的:

[{
  "name": "Employee1",
  "volume": 17,
  "date": "2018/09/10"
}, {
  "name": "Employee1",
  "volume": 20,
  "date": "2018/09/11"
}, {
  "name": "Employee2",
  "volume": 10,
  "date": "2018/09/10"
}, {
  "name": "Employee2",
  "volume": 29,
  "date": "2018/08/11"
}]

然后堆栈调用变为:

 var stack = d3.stack()
    .keys(["Employee1", "Employee2"])     
    .value(function(d,k) { return d.volume; })
    .order(d3.stackOrderNone)
    .offset(d3.stackOffsetNone);

区域生成器:

var area = d3.area()
  .x(function(d, i) { return xScale(d.data.date); })
  .y0(function(d) { return yScale(d[0]); })
  .y1(function(d) { return yScale(d[1]); });