D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
Jboulery
Full window
Github gist
Stocks - Grouped to stacked bars
Built with
blockbuilder.org
<!DOCTYPE html> <meta charset="utf-8"> <style> .axis text { font: 10px sans-serif; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .x.axis path { display: none; } form { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; position: absolute; left: 10px; top: 10px; } label { display: block; } </style> <body> <form> <label><input type="radio" name="mode" value="grouped"> Grouped</label> <label><input type="radio" name="mode" value="stacked" checked> Stacked</label> </form> <svg width="960" height="500"></svg> <script src="//d3js.org/d3.v4.min.js"></script> <script> var svg = d3.select('svg'), margin = {top: 20, right: 30, bottom: 30, left: 40}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var y = d3.scaleLinear() .rangeRound([height, 0]); var x0 = d3.scaleBand() .rangeRound([0, width]) .paddingInner(0.1); var x1 = d3.scaleBand() var color = d3.scaleOrdinal(d3.schemeCategory10); d3.csv("stocks.csv", function(dataset) { data = dataset var pricesByDate = d3.nest() .key(function(d){ return d.date }) .entries(data) var keys = pricesByDate[0].values.map(function(d){ return d.symbol; }); var clean_data = []; pricesByDate.forEach(function(d){ var dict = {}; dict.key = d.key; var sumPrice = 0; var maxPrice = 0; d.values.forEach(function(v){ var price = +v.price; dict[v.symbol] = price; sumPrice += price; if (price > maxPrice){ maxPrice = price; } }); dict.maxPrice = maxPrice; dict.sumPrice = sumPrice; clean_data.push(dict); }); // console.log(clean_data); //clean_data = [{ key: "Mar 2000", MSFT: 43.22, AMZN: 67,... }, ...] var maxSumPrice = d3.max(clean_data, function(d){ return d.sumPrice; }); var maxPrice = d3.max(clean_data, function(d){ return d.maxPrice; }); x0.domain(pricesByDate.map(function(d){ return d.key; })); x1.domain(keys).rangeRound([0, x0.bandwidth()]); y.domain([0, maxSumPrice]).nice();; var stack = d3.stack().keys(keys) var rectGroup = g.append('g') .selectAll('g') .data(stack(clean_data)) .enter().append('g') .attr('fill', function(d){ return color(d.key) }); var rect = rectGroup.selectAll('rect') .data(function(d){ return d; }) .enter().append('rect') .attr('x', function(d){ return x0(d.data.key); }) .attr('y', function(d){ return y(d[1]); }) .attr('height', function(d){ return y(d[0]) - y(d[1]); }) .attr('width', x0.bandwidth()); d3.selectAll('input') .on('change', changed); function changed(){ if (this.value === 'grouped') groupedBars(); else stackedBars(); } function groupedBars(){ y.domain([0, maxPrice]); x0.paddingInner(0); rect .transition().duration(500) .attr('x', function(d){ return x0(d.data.key) + x1(this.parentNode.__data__.key) }) .transition().duration(500) .attr('y', function(d){ return y(d[1] - d[0]); }) .attr('height', function(d){ return y(0) - y(d[1] - d[0]) }) .attr('width', function(d){ return x1.bandwidth(); }); }; function stackedBars(){ y.domain([0, maxSumPrice]); x0.paddingInner(0.1); rect .transition().duration(500) .attr('x', function(d){ return x0(d.data.key); }) .transition().duration(500) .attr('y', function(d){ return y(d[1]); }) .attr('height', function(d){ return y(d[0]) - y(d[1]); }) .attr('width', x0.bandwidth()); } // Legende var legendRectSize = 18; var legendSpacing = 4; var legend = svg.selectAll('.legend') .data(keys) .enter() .append('g') .attr('class', 'legend') .attr('transform', function(d, i){ var horizontal_offset = 2 * legendRectSize ; var vertical_offset = (i+1) * (legendRectSize + legendSpacing) - (legendRectSize + legendSpacing); return 'translate(' + horizontal_offset + ', ' + (vertical_offset + 100) + ')'; }); legend.append('rect') .attr('width', legendRectSize) .attr('height', legendRectSize) .style('fill', color) .style('stroke', color); legend.append('text') .attr('x', legendRectSize + legendSpacing) .attr('y', legendRectSize - legendSpacing) .text(function(d) { return d; }); }); </script>
https://d3js.org/d3.v4.min.js