【问题标题】:Stacked bar chart, y domain堆积条形图,y 域
【发布时间】:2018-01-07 20:53:44
【问题描述】:

我这里有个小伙子https://plnkr.co/edit/hBWoIIyzcHELGyewOyZE?p=preview

我正在尝试创建一个简单的堆积条形图。

条形图位于图表顶部上方,我认为这是域的问题

我还需要 y 轴上的刻度,我认为这与 y 域有关。

是 y 域控制 y 轴上显示的条形和刻度的高度

y.domain([0, d3.max(data, (d)=>{
    return d
})]) 

【问题讨论】:

    标签: d3.js


    【解决方案1】:

    这是迄今为止的问题列表:

    首先,您的y 域设置不正确。它应该使用堆叠的数据:

    y.domain([0, d3.max(stackedSeries, function(d) {
        return d3.max(d, function(d) {
            return d[0] + d[1];
        });
    })])
    

    其次,矩形的yheight 的数学运算是错误的。应该是:

    .attr('height', (d) => {
        return y(d[0]) - y(d[0] + d[1]);
    })
    
    .attr('y', (d) => {
        return y(d[0] + d[1]);
    })
    

    最后,为x 位置使用x 比例:

    .attr('x', (d, i) => {
        return x(d.data.day)
    })
    

    以下是这些更改的代码:

    var margin = {
      top: 40,
      right: 20,
      bottom: 40,
      left: 40
    }
    
    var width = 400 - margin.left - margin.right
    var height = 500 - margin.top - margin.bottom
    
    var data = [{
        day: 'Mon',
        apricots: 120,
        blueberries: 180,
        cherries: 100
      },
      {
        day: 'Tue',
        apricots: 60,
        blueberries: 185,
        cherries: 105
      },
      {
        day: 'Wed',
        apricots: 100,
        blueberries: 215,
        cherries: 110
      },
      {
        day: 'Thu',
        apricots: 150,
        blueberries: 330,
        cherries: 105
      },
      {
        day: 'Fri',
        apricots: 120,
        blueberries: 240,
        cherries: 105
      }
    ];
    
    var svg = d3.select('body')
      .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 + ')')
    
    var colors = ['#FBB65B', '#513551', '#de3163'];
    
    var stack = d3.stack()
      .keys(['apricots', 'blueberries', 'cherries']);
    
    var stackedSeries = stack(data);
    
    // Create a g element for each series
    var g = d3.select('g')
      .selectAll('g.series')
      .data(stackedSeries)
      .enter()
      .append('g')
      .classed('series', true)
      .style('fill', (d, i) => {
        return colors[i];
      });
    
    var x = d3.scaleBand()
      .rangeRound([0, width])
      .padding(0.1)
    
    var y = d3.scaleLinear()
      .range([height, 0])
    
    x.domain(data.map((d) => {
      return d.day
    }))
    
    y.domain([0, d3.max(stackedSeries, function(d) {
      return d3.max(d, function(d) {
        return d[0] + d[1];
      });
    })])
    
    svg.append('g')
      .attr('class', 'x axis')
      .attr('transform', 'translate(0, ' + height + ')')
      .call(d3.axisBottom(x))
    
    svg.append('g')
      .attr('class', 'y axis')
      .call(d3.axisLeft(y))
    
    // For each series create a rect element for each day
    g.selectAll('rect')
      .data((d) => {
        return d;
      })
      .enter()
      .append('rect')
      .attr('height', (d) => {
        return y(d[0]) - y(d[0] + d[1]);
      })
    
      .attr('y', (d) => {
        return y(d[0] + d[1]);
      })
      .attr('x', (d, i) => {
        return x(d.data.day)
      })
    
      .attr('width', x.bandwidth())
      .style("stroke", "#ccc");
    <script src="https://d3js.org/d3.v4.min.js"></script>

    【讨论】: