简体   繁体   English

未在 D3 堆积条形图中绘制的条形图

[英]Bars not plotted in D3 stacked bar chart

I have built a stacked chart using d3.我使用 d3 构建了一个堆积图。 But first data is plotted, but the second data is not getting plotted.但是绘制了第一个数据,但未绘制第二个数据。 The data is being fetched from an API, and the numbers possibly will have a huge difference.数据是从 API 获取的,数字可能会有很大差异。 In the first data, E is not plotted in graph and the bar exceeds height of Y-axis.在第一个数据中,E 未绘制在图形中并且条形超出 Y 轴的高度。 And, second one is not drawn at all.而且,第二个根本没有绘制。 How to fix this.如何解决这个问题。 I checked several examples and the code I followed is same I think.我检查了几个例子,我认为我遵循的代码是一样的。 I cannot figure out what's wrong.我无法弄清楚出了什么问题。

Also, here I have given a fixed bar size.另外,这里我给出了一个固定的条形尺寸。 The bar is not drawn in the center, but towards left.条形图不是画在中间,而是画在左边。 I needed each bar to be plotted in the middle.我需要在中间绘制每个条形图。

Code,代码,

const data = [
{'category': 'Type 1', A: 0, B: 1402574577, C: 0, D: 19197208547, E: 1792937}, {category: 'Type 2', A: 14600000, B: 0, C: 0, D: 0, E: 2369530}]
const keys = ['A', 'B', 'C', 'D', 'E']
const cost = [
    [0, 1402574577, 0 , 19197208547, 1792937],
    [14600000, 0, 0, 0, 2369530]
]

const width = 500;
const height = 300;
const margin = {left: 100, top: 60, right: 60};

let svg = d3
      .select('#stackedbars')
      .append('svg')
      .attr('width', width + margin.left + margin.right)
      .attr('height', height + margin.top * 2)
      .style('background', '#fff');
      
svg = svg.append('g')
      .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

const xScaleRange = data.length * 120;

const x = d3.scaleBand()
         .rangeRound([0, xScaleRange])
         .padding(0.1)
         
const y = d3.scaleLinear()
          .range([height, 0]);
  
const z = d3.scaleOrdinal()
          .domain(keys)
          .range(["#F6D7A7", "#F6EABE", "#C8E3D4", "#87AAAA", "#247291"]);
x.domain(data.map(d => d.category));
y.domain([0, d3.max(cost.flat())]).nice()

const gX = svg.append('g')
  .attr('class', 'axis')
  .attr('transform', `translate(0,${height})`)
  .call(d3.axisBottom(x).tickSizeOuter(0))
  .call(g => g.selectAll('.tick > line')
  .filter((d, i, nodes) => i < nodes.length - 1)
  .clone()
  .attr('stroke', '#cccccc')
  .attr('x1', x.step() / 2)
  .attr('x2', x.step() / 2)
  .attr('y1', -height)
  .attr('y2', 0));

const gY = svg.append('g')
  .attr('class', 'axis')
  .call(d3.axisLeft(y).ticks(null, 's').tickFormat(d => d))
  .call(g => g.selectAll('.tick > line')
  .filter((d, i) => i > 0)
  .clone()
  .attr('stroke', '#cccccc')
  .attr('x1', 0)
  .attr('x2', width));

gX.selectAll("line")
  .style("stroke", "#eeeeee");

gX.selectAll("path")
  .style("stroke", "#eeeeee");

gY.selectAll("line")
  .style("stroke", "#eeeeee");

gY.selectAll("path")
  .style("stroke", "#eeeeee");

gY.selectAll("text")
  .style("fill", "#8a8a8a");
  
const dataStackLayout = d3.stack().keys(keys)(data);
const layer = svg.selectAll(".stack")
    .data(dataStackLayout)
    .enter().append("g")
    .attr("class", "stack")
    .style("fill",  (d) => {
      return z(d.key)
    });

layer.selectAll("rect")
  .data(d => d)
  .enter().append("rect")
  .attr("x", d => {
    return x(d.data.category)
  })
  .attr("y",  d => y(d[1]))
  .attr("height", d => y(d[0]) - y(d[1]))
  .attr("width", "25")

Your code is basically correct.你的代码基本上是正确的。 The problem is with values and scales.问题在于价值观和尺度。 See an example in the snippet:请参阅代码段中的示例:

 const data = [ {'category': 'Type 1', A: 10, B: 20, C: 30, D: 40, E: 50}, {category: 'Type 2', A: 50, B: 40, C: 30, D: 20, E: 10}] const keys = ['A', 'B', 'C', 'D', 'E'] const colors = { 'A': 'red', 'B': 'green', 'C': 'blue', 'D': 'yellow', 'E': 'orange' }; const width = 500; const height = 300; const margin = {left: 100, top: 60, right: 60}; let svg = d3 .select('#stackedbars') .append('svg') .attr('width', width + margin.left + margin.right) .attr('height', height + margin.top * 2) .style('background', '#fff'); svg = svg.append('g') .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); const xScaleRange = data.length * 120; const x = d3.scaleBand() .rangeRound([0, xScaleRange]) .padding(0.1) const y = d3.scaleLinear() .domain([0, 200]) .range([height, 0]); x.domain(data.map(d => d.category)); const gX = svg.append('g') .attr('class', 'axis') .attr('transform', `translate(0,${height})`) .call(d3.axisBottom(x).tickSizeOuter(0)) .call(g => g.selectAll('.tick > line') .filter((d, i, nodes) => i < nodes.length - 1) .clone() .attr('stroke', '#cccccc') .attr('x1', x.step() / 2) .attr('x2', x.step() / 2) .attr('y1', -height) .attr('y2', 0)); const gY = svg.append('g') .attr('class', 'axis') .call(d3.axisLeft(y).ticks(null, 's').tickFormat(d => d)) .call(g => g.selectAll('.tick > line') .filter((d, i) => i > 0) .clone() .attr('stroke', '#cccccc') .attr('x1', 0) .attr('x2', width)); gX.selectAll("line") .style("stroke", "#eeeeee"); gX.selectAll("path") .style("stroke", "#eeeeee"); gY.selectAll("line") .style("stroke", "#eeeeee"); gY.selectAll("path") .style("stroke", "#eeeeee"); gY.selectAll("text") .style("fill", "#8a8a8a"); const dataStackLayout = d3.stack().keys(keys)(data); const layer = svg.selectAll(".stack") .data(dataStackLayout) .enter().append("g") .attr("class", "stack") .style("fill", (d) => { return colors[d.key] }); layer.selectAll("rect") .data(d => d) .enter().append("rect") .attr("x", d => { return x(d.data.category) + 35 }) .attr("y", d => y(d[1])) .attr("height", d => y(d[0]) - y(d[1])) .attr("width", 30)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <div id="stackedbars" />

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM