D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
jdmarlin
Full window
Github gist
Stacked Bar Chart
Surplus or Deficit Bar Chart
<!DOCTYPE html> <head> <meta charset="utf-8"> <script src="https://d3js.org/d3.v4.min.js"></script> <style> body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; } </style> </head> <body> <script> const data = [ { 'package': 'AAPL', 'nominal': '-100.0', 'financing_type': 'pay' }, { 'package': 'AAPL', 'nominal': '-200.0', 'financing_type': 'pay' }, { 'package': 'AAPL', 'nominal': '150.0', 'financing_type': 'receive' }, { 'package': 'AAPL', 'nominal': '160.0', 'financing_type': 'receive' }, { 'package': 'AMZN', 'nominal': '100', 'financing_type': 'receive' }, { 'package': 'AMZN', 'nominal': '-110', 'financing_type': 'pay' } ] const nestData = d3.nest() .key(d => d.package) .rollup(packages => { let obj = {}; let netNominal = d3.sum(packages, d => d.nominal); netNominal >= 0 ? key = 'surplus' : key = 'deficit' obj[key] = Math.abs(netNominal); let nominal = d3.nest() .key(d => d.financing_type) .rollup(financing => d3.sum(financing, d => d.nominal)) .entries(packages) nominal = nominal.length > 1 ? d3.min(nominal, d => Math.abs(d.value)) : 0 obj['package'] = packages[0].package obj['nominal'] = nominal obj['total'] = obj['nominal'] + obj[key] return obj }) .entries(data) var svg = d3.select("body").append("svg") .attr("width", 200) .attr("height", 500) let margin = {top: 20, right: 20, bottom: 30, left: 40} let width = svg.attr('width') - margin.left - margin.right let height = svg.attr('height') - margin.top - margin.bottom let g = svg.append('g') .attr('transform', `translate(${margin.left}, ${margin.top})`) var x = d3.scaleBand() .domain(nestData.map(d => d.key)) .rangeRound([0, width]) // .padding(0.01) .paddingInner(0.05) // .align(0.1); var y = d3.scaleLinear() .domain([0, d3.max(nestData, d => d.value.total)]) .rangeRound([height, 0]).nice() var z = d3.scaleOrdinal() .range(["#dbdbdb", "#00b774", "#fe434f"]); g.append('g') .attr('class', 'axis x-axis') .attr('transform', `translate(0, ${height})`) .call(d3.axisBottom(x)) g.append('g') .attr('class', 'axis y-axis') .call(d3.axisLeft(y).ticks(null, 's')) g.append('g') .selectAll('g') .data(d3.stack().keys(['nominal', 'surplus', 'deficit'])(nestData.map(d => d.value))) .enter().append("g") .attr("fill", function(d) { return z(d.key); }) .selectAll("rect") .data(d => d) .enter().append("rect") .attr('x', d => x(d.data.package)) .attr('y', d => y(d[1])) .attr('height', d => (y(d[0]) - y(d[1]))) .attr('width', x.bandwidth()) </script> </body>
https://d3js.org/d3.v4.min.js