d3:histogram

by Richard Hunter

HTML

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

CSS

svg {
  background: lightgoldenrodyellow;
}

.line {
  fill: none;
  stroke-width: 2;
  stroke: teal;
}

JavaScript

const data = [
  [0, 5, 4180, 836],
  [5, 5, 13687, 2737],
  [10, 5, 18618, 3723],
  [15, 5, 19634, 3926],

  [20, 5, 17981, 3596],
  [25, 5, 7190, 1438],
  [30, 5, 16369, 3273],
  [35, 5, 3212, 642],
  [40, 5, 4122, 824],
  [45, 15, 9200, 613],
  [60, 30, 6461, 215],
  [90, 60, 3435, 57]
];

const width = 600;
const height = 300;

const margin = {
  top: 30,
  right: 50,
  bottom: 40,
  left: 50,
};

const xScale = d3.scaleLinear()
  .domain([
    0,
    d3.max(data, d => d[0] + d[1]),
  ])
  .range([0, width])

const yScale = d3.scaleLinear()
  .domain([
    0,
    d3.max(data, d => d[3])
  ])
  .range([
    height, 0
  ]);

function calculateWidth(d) {
  const x1 = d[0]
  const domainWidth = d[1];
  const x2 = x1 + domainWidth

  const _x1 = xScale(x1);
  const _x2 = xScale(x2);

  return _x2 - _x1;
}

const 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})`)

svg.append('g')
  .selectAll('rect')
  .data(data)
  .enter()
  .append('rect')
  .attr('x', d => xScale(d[0]) + 1)
  .attr('y', d => yScale(d[3]))
  .attr('width', d => calculateWidth(d) - 1)
  .attr('height', d => height - yScale(d[3]))
  .attr('fill', 'blue')

const xAxis = d3.axisBottom(xScale).ticks(20);
const yAxis = d3.axisLeft(yScale).ticks(20);

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

svg.append('g')
  .call(yAxis);