d3:stacked-bar-chart

by Richard Hunter

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.min.js"></script>

JavaScript

const width = 500;
const height = 400;

const margin = {
  top: 10,
  right: 20,
  bottom: 30,
  left: 30,
};

const data = [{
    category: 'football',
    male: 2,
    female: 2,
    nonBinary: 1
  },
  {
    category: 'tennis',
    male: 1,
    female: 6,
    nonBinary: 1,
  },
  {
    category: 'athletics',
    male: 4,
    female: 2,
    nonBinary: 2
  },
  {
    category: 'gymnastics',
    male: 1,
    female: 2,
    nonBinary: 0
  },
  {
    category: 'chess',
    male: 2,
    female: 4,
    nonBinary: 1,
  },
];

const colors = d3.scaleOrdinal(d3.schemeCategory10);

const stack = d3.stack()
  .keys(["male", "female", "nonBinary"])
  .order(d3.stackOrderAscending);

const series = stack(data);

const xScale = d3
  .scaleBand()
  .domain(d3.range(data.length))
  .range([margin.left, width])
  .paddingInner(0.5)
  .paddingOuter(0.4)

const xAxis = d3.axisBottom(xScale).tickFormat(d => {
	return data[d].category;
});

const yScale = d3
  .scaleLinear()
  .domain([
    d3.max(data, d => d.male + d.female + d.nonBinary),
    0
  ])
  .range([margin.top, height - margin.bottom]);

const yAxis = d3.axisLeft(yScale).ticks(5);

const svg = d3.select("body").append("svg").attr("width", width).attr("height", height);

const groups = svg.selectAll("g").data(series)
  .enter()
  .append("g")
  .style("fill", (d, i) => colors(i));

const rects = groups.selectAll("rect").data(d => d).enter()
  .append("rect")
  .attr("x", (d, i) => xScale(i))
  .attr("y", d => yScale(d[1]))
  .attr("height", d => yScale(d[0]) - yScale(d[1]))
  .attr("width", xScale.bandwidth());

svg.append('g').attr('transform', `translate(0, ${height - margin.bottom})`).call(xAxis);
svg.append('g').attr('transform', `translate(${margin.left}, 0)`).call(yAxis);