rguttersohn
rguttersohn

Reputation: 484

How do I set the X values for a singled stacked horizontal bar chart using d3.js?

I am trying to set the x attribute values of single stacked horizontal bar chart. After messing with javascript for about an hour, I can't seem to get the x values lined up so that the bars line up one after the other from largest value to smallest.

Below is my js:


const abuseNeglectData = [
  {
    type: "Neglected-Related",
    data: 122214,
    color: "red",
  },
  {
    type: "Abuse-Related",
    data: 47364,
    color: "orange",
  },
  {
    type: "Other",
    data: 2972,
    color: "blue",
  },
];
dataSum = d3.sum(abuseNeglectData, d=>{return d.data})

const width = 400,
  height = 100,
  bottom = 20,
  xScale = d3
    .scaleLinear()
    .range([0,width])
    .domain([
      0,dataSum
    ]),
    xBand = d3.scaleBand()
    .range([0,width])
    .domain(abuseNeglectData.map(d=>{return d.data}));

    const svg = d3.select('.graph-wrapper.abuse-neglect').append('svg')
    .attr('width', width)
    .attr('height', height + bottom);
    svg.append('g').attr('class','bars').selectAll('rect')
    .data(abuseNeglectData)
    .enter()
    .append('rect')
    .attr('y', d=>{return 0})
    .attr('height',d=>{return height})
    .style('width',d=> {return xScale(d.data)+'px'})
    .style('fill', d=>{return d.color})
    .attr('x',d=>{return xBand(d.data)})

    //xaxis

    svg.append('g').attr('class','x-axis')
    .call(d3.axisBottom(xBand))
    .attr('transform',`translate(0,${height})`)


Thanks for the help.

Upvotes: 1

Views: 80

Answers (1)

Tom Shanley
Tom Shanley

Reputation: 1787

You can manually calculate the x coordinate for each bar based on the preceding elements' values, which offsets the rect. The example below does that within a forEach loop.

    const abuseNeglectData = [
  {
    type: "Neglected-Related",
    data: 122214,
    color: "red",
  },
  {
    type: "Abuse-Related",
    data: 47364,
    color: "orange",
  },
  {
    type: "Other",
    data: 2972,
    color: "blue",
  },
];
dataSum = d3.sum(abuseNeglectData, d=>{return d.data})

let offset = 0

abuseNeglectData.forEach(function(d){
  d.offset = offset
  offset = offset + d.data
})


const width = 400,
  height = 100,
  bottom = 20,
  
      xScale = d3
    .scaleLinear()
    .range([0,width])
    .domain([
      0,dataSum
    ]);
    
 
    const svg = d3.select('body'/*'.graph-wrapper.abuse-neglect'*/).append('svg')
    .attr('width', width)
    .attr('height', height + bottom);
    
    svg.append('g').attr('class','bars').selectAll('rect')
    .data(abuseNeglectData)
    .enter()
    .append('rect')
    .attr('y', d=>{return 0})
    .attr('height',d=>{return height})
    .style('width',d=> {return xScale(d.data)+'px'})
    .style('fill', d=>{return d.color})
    .attr('x',d=>{return xScale(d.offset)})


    svg.append('g').attr('class','x-axis')
    .call(d3.axisBottom(xScale))
    .attr('transform',`translate(0,${height})`)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

Upvotes: 2

Related Questions