Fines incurred by colleges racing in the Cambridge May Bumps races.
Visit http://www.cambridgebumps.com/fines/ for more details.
Also an attempt at implementing some of Amy Cesal's style guidelines
xxxxxxxxxx
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>May Bumps Fines</title>
<style>
html {
height: 100%;
}
body {
height: 100vh;
margin: 0px;
display: flex;
font-family: sans-serif;
background-color: #f0ece9;
flex-direction: column;
overflow: hidden;
}
#header {
background-color: #f5f3f2;
padding-left: 22px;
padding-top: 12px;
border-bottom: 1px solid white;
}
#header #headline {
display: flex;
flex-direction: row;
justify-content: space-between;
}
#header h1 {
font-family: Helvetica, sans-serif;
font-size: 20px;
color: #635f5d;
margin-top: 0px;
margin-bottom: 5px;
}
#header p {
font-family: Georgia, serif;
font-size: 14px;
font-style: italic;
color: #8e8883;
margin-top: 5px;
margin-bottom: 5px;
}
#footer {
height: 22px;
line-height: 22px;
font-family: Georgia, serif;
font-size: 12px;
color: #625e5b;
background-color: #e6e2df;
padding-left: 22px;
border-top: 1px dashed #cdcdc9;
}
#footer span {
display: inline-block;
vertical-align: middle;
}
div#chart {
flex: 1;
}
.title {
font-family: Helvetica, sans-serif;
font-size: 30px;
fill: #625e5b;
}
.dropdown {
color: #635f5d;
font-family: Helvetica, sans-serif;
font-size: 16px;
padding-right: 12px;
}
.dropdown select {
color: #635f5d;
font-family: Helvetica, sans-serif;
font-size: 16px;
}
svg text {
fill: #635f5d;
}
#quantity {
display: none;
}
.axis--x path {
display: none;
}
.axis--x .tick line {
display: none;
}
.axis--x {
font-size: 2vw;
}
.label {
font-size: 2vw;
}
.axis--y {
font-size: 2vw;
}
.axis--y .domain {
display: none;
}
.axis--y .tick line {
stroke: white;
}
@media screen and (max-width: 500px) {
.axis--x {
font-size: 10px;
}
.axis--y {
font-size: 10px;
}
.label {
font-size: 10px;
}
}
@media screen and (min-width: 800px) {
.axis--x {
font-size: 16px;
}
.axis--y {
font-size: 16px;
}
.label {
font-size: 16px;
}
}
</style>
<div id="header">
<div id="headline">
<h1>May Bumps Fines</h1>
<div class="dropdown" id="year"><label>Year: </label><select></select></div>
</div>
<p>Total fines incurred over four days of racing</p>
</div>
<div id="chart"></div>
<div id="footer">
<span><b>Source</b>: <i>CUCBC mailing lists</i></span>
</div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
d3.csv("data.csv", function (d) {
d.amount = +d.amount;
return d;
}, function (error, data) {
if (error) throw error;
var barChart = chart();
var nestedData = d3.nest()
.key(function (d) { return d.year; }).sortKeys(d3.ascending)
.key(function (d) { return d.college; }).sortKeys(d3.ascending)
.rollup(function (leaves) { return { "number": leaves.length, "total_amount": d3.sum(leaves, function (d) { return +d.amount; }) } })
.entries(data);
var menuYear = d3.select("#year select")
.on("change", () => change(false));
menuYear.selectAll("option")
.data(nestedData)
.enter().append("option")
.text(function (d) { return d.key; });
menuYear.property("value", "2017");
var change = function (isResize) {
var year = menuYear.property("value");
var currentData = nestedData.find(function (d) { return d.key === year }).values
.map(function (d) { return { key: d.key, value: d.value.total_amount }; })
.sort(function (a, b) { return b.value - a.value; });
var selection = d3.select("#chart");
selection.datum(currentData).call(barChart, isResize);
}
window.onresize = function () {
change(true);
}
change(false);
});
var chart = function () {
var svg = null;
var width;
var height;
var chartWidth;
var chartHeight;
var x;
var y;
function chart(selection, isResize) {
selection.each(function (data) {
var duration = isResize ? 0 : 1000;
width = selection.node().getBoundingClientRect().width;
height = selection.node().getBoundingClientRect().height;
var ratio = (width - 500) / (800 - 500);
var clampedRatio = Math.max(0, Math.min(1, ratio));
var marginBottom = 80 + 48 * clampedRatio;
var marginLeft = 48 + 24 * clampedRatio;
var margin = {
top: 22,
right: 10,
bottom: marginBottom,
left: marginLeft
};
chartWidth = width - margin.left - margin.right;
chartHeight = height - margin.top - margin.bottom;
if (!svg) {
svg = selection.append("svg")
.style("vertical-align", "bottom"); // <-- Makes all the difference
var g = svg.append("g");
g.append("g")
.attr("class", "axis axis--x");
g.append("g")
.attr("class", "axis axis--y");
svg.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.attr("dy", "0.71em")
.attr("text-anchor", "middle")
.text("Total Amount (£)");
}
svg.attr("height", "100%")
.attr("width", width);
svg.select("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.select(".title")
.attr("x", width - margin.right);
svg.select(".label")
.attr("x", -chartHeight / 2)
.attr("y", 8);
d3.select("#year")
.style("right", margin.right + "px")
.style("top", (12 + 13.4) + "px");
d3.select("#quantity")
.style("right", margin.right + "px")
.style("top", (margin.top + 50) + "px");
x = d3.scaleBand().range([0, chartWidth]).padding(0.1);
y = d3.scaleLinear().rangeRound([chartHeight, 0]);
x.domain(data.map(function (d) { return d.key; }));
y.domain([0, d3.max(data, function (d) { return d.value; })]).nice();
var t = d3.transition()
.duration(duration);
var xAxis = svg.select(".axis--x")
.attr("transform", "translate(0," + chartHeight + ")");
xAxis.transition()
.duration(duration)
.call(d3.axisBottom(x))
.selectAll("text")
.attr("y", 0);
xAxis.selectAll("text")
.attr("y", 0)
.attr("x", -5)
.attr("dy", ".35em")
.attr("transform", "rotate(-90)")
.style("text-anchor", "end");
svg.select(".axis--y")
.transition(t)
.delay(duration)
.call(d3.axisLeft(y).tickSize(-width));
var bars = svg.select('g')
.selectAll(".bar")
.data(data, function (d) { return d.key; });
bars
.transition(t)
.attr("x", function (d) { return x(d.key); })
.attr("width", x.bandwidth())
.transition(t)
.attr("y", function (d) { return y(d.value); })
.attr("height", function (d) { return chartHeight - y(d.value); })
.style("fill", function (d) { return "#e6842a"; });
bars.enter()
.append("rect")
.attr("class", "bar")
.attr("x", function (d) { return x(d.key); })
.attr("y", function (d) { return y(0); })
.attr("width", x.bandwidth())
.style("fill", function (d) { return "#e6842a"; })
.transition(t)
.delay(duration)
.attr("y", function (d) { return y(d.value); })
.attr("height", function (d) { return chartHeight - y(d.value); });
bars.exit()
.attr("opacity", 1)
.transition(t)
.attr("y", function (d) { return y(0); })
.attr("height", function (d) { return 0; })
.attr("opacity", 0)
.remove();
});
}
return chart;
}
</script>
https://d3js.org/d3.v4.min.js