This grouped bar chart is constructed from a CSV file storing the populations of different states by age group. The chart employs conventional margins and a number of D3 features:
forked from mbostock's block: Grouped Bar Chart
xxxxxxxxxx
<div class="pc-123 pc-chart"></div><!-- outputted via the shortcode. -->
<style>
.pc-chart .svg-area { fill: #bbb; }
.pc-chart .chart-area { fill: #ececec; }
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
<script src="pcUtility.js"></script>
<script>
(function () {
// todo:
//
// 1. Abstract out the duplicate code from update and resize into a utility function.
// 3. Add resize function.
// 4. Allow customization of attributes (font size etc.) in the utility functions too. Maybe via global config object.
// 5. Need to make sure we can add multiple charts to the same page, including the same chart (just to check for bugs).
// 6. Manage ticks at small sizes?
// 7. Add vars to set container width, or let it be 100% width.
var lblTxt = { x: 'states', y: 'population', title: 'population vs states' };
var data, keys, svg, dim, ar = 0.4, w, h, cw, ch, chartEl = '.pc-123', x0, x1, y, z;
var visibleEl = { legend: true, xLbl: true, yLbl: true, chartLbl: true };
var chartOffset = { xLbl: 0, yLbl: 0, chartLbl: 0, legend: 23 },
margin = {top: 45, right: 20, bottom: 45, left: 65};
function defineScales() {
// define scales
x0 = d3.scaleBand().rangeRound([0, dim.cw]).paddingInner(0.1);
x1 = d3.scaleBand().padding(0.05);
y = d3.scaleLinear().rangeRound([dim.ch, 0]);
z = d3.scaleOrdinal().range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]);
}
// process data
d3.csv("data.csv", formatData, function(error, fileData) {
if (error) throw error;
data = fileData;
keys = data.columns.slice(1);
fields = data.columns.slice();
dim = pcChartDimensions(chartEl, ar, margin);
svg = pcCreateSVG(chartEl, dim, margin); defineScales();
pcSetupVisibleElements(svg, dim, z, margin, visibleEl, fields);
update(); // update chart
});
function update() {
x0.domain(data.map(function(d) { return d[fields[0]]; }));
x1.domain(keys).rangeRound([0, x0.bandwidth()]);
y.domain([0, d3.max(data, function(d) { return d3.max(keys, function(key) { return d[key]; }); })]).nice();
// create bars
svg.select('.pc-bars-g')
.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d) { return "translate(" + x0(d[fields[0]]) + ",0)"; })
.selectAll("rect")
.data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })
.enter().append("rect")
.attr('class', function(d,i) { return 'bar' + (i + 1); } )
.attrs({
x: function(d) { return x1(d.key); },
y: function(d) { return y(d.value); },
width: function () {return x1.bandwidth() },
height: function(d) { return dim.ch - y(d.value); },
fill: function(d) { return z(d.key); }
});
svg.select('.x-axis')
.call(d3.axisBottom(x0));
svg.select('.y-axis')
.call(d3.axisLeft(y).ticks(null, "s"));
// update axis labels, chart title, and legend
pcUpdateVisibleElements(svg, visibleEl, keys, dim, chartOffset, z, lblTxt, margin);
}
function formatData(d, i, columns) {
for (var i = 1, n = columns.length; i < n; ++i) d[columns[i]] = +d[columns[i]];
return d;
}
})();
</script>
https://d3js.org/d3.v4.min.js
https://d3js.org/d3-selection-multi.v1.min.js