const queue = d3_queue.queue(); queue .defer(d3.json, 'data.json') .await(render); function render(error, data) { const seriesKeys = Object.keys(data[0]).slice(0, Object.keys(data[0]).length - 1); console.log('Object.keys(data[0])', Object.keys(data[0])); console.log('seriesKeys', seriesKeys); const stackedData = d3.stack() .keys(seriesKeys)(data); const yMaxGrouped = d3.max(data, d => d3.max(Object.values(d))); const yMaxStacked = d3.max(data, d => d3.sum(Object.values(d))); const n = Object.keys(data[0]).length; // the number of series const m = d3.range(data.length); // the number of values per series console.log('stackedData', stackedData); console.log('yMaxGrouped', yMaxGrouped); console.log('yMaxStacked', yMaxStacked); console.log('n, the number of series', n); console.log('m, the number of values per series', m); const svg = d3.select('svg'); const controlHeight = 50; const margin = {top: 10, right: 10, bottom: 20, left: 10}; const width = +svg.attr('width') - margin.left - margin.right; const height = +svg.attr('height') - controlHeight - margin.top - margin.bottom; const g = svg.append('g') .attr('transform', `translate(${margin.left},${margin.top})`); const x = d3.scaleBand() .domain(m) .rangeRound([0, width]) .padding(0.08); const y = d3.scaleLinear() .domain([0, yMaxStacked]) .range([height, 0]); const color = d3.scaleOrdinal() .domain(d3.range(n)) .range(d3.schemeCategory20c.slice(8, 12)); // greens const series = g.selectAll('.series') .data(stackedData) .enter().append('g') .attr('fill', (d, i) => color(i)); const rect = series.selectAll('rect') .data(d => d) .enter().append('rect') .attr('x', (d, i) => x(i)) .attr('y', height) .attr('width', x.bandwidth()) .attr('height', 0); rect.transition() .delay((d, i) => i * 10) .attr('y', d => y(d[1])) .attr('height', d => y(d[0]) - y(d[1])); g.append('g') .attr('class', 'axis axis--x') .attr('transform', `translate(0,${height})`) .call(d3.axisBottom(x) .tickSize(0) .tickPadding(6)); d3.selectAll('input') .on('change', changed); const timeout = d3.timeout(() => { d3.select('input[value=\'grouped\']') .property('checked', true) .dispatch('change'); }, 2000); function changed() { timeout.stop(); if (this.value === 'grouped') transitionGrouped(); else transitionStacked(); } function transitionGrouped() { y.domain([0, yMaxGrouped]); rect.transition() .duration(500) .delay((d, i) => i * 10) .attr('x', function(d, i) { return x(i) + x.bandwidth() / n * this.parentNode.__data__.key; }) .attr('width', x.bandwidth() / n) .transition() .attr('y', d => y(d[1] - d[0])) .attr('height', d => y(0) - y(d[1] - d[0])); } function transitionStacked() { y.domain([0, yMaxStacked]); rect.transition() .duration(500) .delay((d, i) => i * 10) .attr('y', d => y(d[1])) .attr('height', d => y(d[0]) - y(d[1])) .transition() .attr('x', (d, i) => x(i)) .attr('width', x.bandwidth()); } }