xxxxxxxxxx
<html lang="en">
<head>
<meta charset="utf-8">
<title>Historic Dipsea Results with D3</title>
<script type="text/javascript" src="https://d3js.org/d3.v3.js"></script>
<style type="text/css">
body {
background-color: white;
}
h1 {
font-family: sans-serif;
font-size: 24px;
margin: 0;
}
p {
font-family: sans-serif;
font-size: 14px;
margin: 10px 0 0 0;
}
.linelabel {
font-family: sans-serif;
font-size: 10px;
}
.linelabel.fastest {
fill:grey;
}
.linelabel.winner {
fill:orange;
}
svg {
background-color: white;
}
.circle {
stroke: none;
}
.circle.men {
fill: steelblue;
stroke: steelblue;
stroke-width: 0px;
}
.circle.women {
fill: red;
stroke: red;
stroke-width: 0px;
}
.circle:hover {
stroke-width: 4px;
}
.line.winner.actual {
fill: none;
stroke: orange;
opacity: 0.5;
stroke-width: 1px;
}
.line.winner.clock {
fill: none;
stroke: orange;
stroke-width: 2px;
}
.line.fastest.actual {
fill: none;
stroke: grey;
stroke-width: 2px;
}
.line.fastest.clock {
fill: none;
stroke: pink;
stroke-width: 2px;
}
.area.winner {
fill: orange;
opacity: 0.05;
stroke: none;
}
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
.y.axis path,
.y.axis line {
opacity: 0;
}
.y.grid {
stroke: lightgrey;
opacity: 0.5;
}
.grid path {
stroke-width: 0;
}
</style>
</head>
<body>
<h1>The Dipsea Race</h1>
<p>Overall winner and fastest net times by year. In the last 20 years, the fastest runner has not successfully won the race due to the unique age- and gender-handicapping system (represented by the shaded region). Colored dots represent gender of winner. (Source: <a href="https://www.dipsea.org">dipsea.org</a>)</p>
<!-- <span id="35" class="p">Top 35 Only </span><span id="1000">All </span><p> -->
<script type="text/javascript">
//Set variables
var dataset;
var dataset_winner = [];
var dataset_fastest = [];
var svgwidth = 700;
var svgheight = 400;
var margin = {top: 50, right: 100, bottom: 50, left: 75 };
var w = svgwidth - margin.left - margin.right;
var h = svgheight - margin.top - margin.bottom;
//Set time formats
var yearFormat = d3.time.format("%Y");
var timeFormat = d3.time.format("%X");
//Set scales
var xScale = d3.time.scale()
.range([ 0, w ]);
var yScale = d3.time.scale()
.range([ 0, h ]);
//Set axis generators
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(10)
.tickFormat(function(d) {
return yearFormat(d);
});
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(8)
.tickFormat(function(d) {
return timeFormat(d);
});
//Configure line generator
var line_actual = d3.svg.line()
.x(function(d) {
return xScale(yearFormat.parse(d.Year));
})
.y(function(d) {
return yScale(timeFormat.parse(d.ActualTime));
});
var line_clock = d3.svg.line()
.x(function(d) {
return xScale(yearFormat.parse(d.Year));
})
.y(function(d) {
return yScale(timeFormat.parse(d.ClockTime));
});
var area = d3.svg.area()
.x(function(d) {
return xScale(yearFormat.parse(d.Year));
})
.y0(function(d) {
return yScale(timeFormat.parse(d.ClockTime));
})
.y1(function(d) {
return yScale(timeFormat.parse(d.ActualTime));
});
//Create SVG canvas
var svg = d3.select("body")
.append("svg")
.attr("width", svgwidth)
.attr("height", svgheight)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//Load in contents of CSV file
d3.csv("dipsea_filtered.csv", function(data) {
//Filter data set
var years = [ "1996", "1997", "1998", "1999", "2000", "2001", "2002", "2003", "2004", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014" ];
for (var i=0; i < years.length; i++) {
var dataset_tmp = data
.filter(function(d) { return d.Year == years[i] });
dataset_fastest[i] = {
Year: years[i],
ActualTime: d3.min(dataset_tmp, function(d) { return d.ActualTime; })
//HeadStart: d3.min(dataset_tmp, function(d) { return d.ActualTime + timeFormat.parse("00:".concat("02").concat(":00")); })
};
}
dataset_winner = data
.filter(function(d) { return d.Place == 1 });
//Set x and y domain
xScale.domain([
d3.min(years, function(d) {
return yearFormat.parse(d);
}),
d3.max(years, function(d) {
return yearFormat.parse(d);
})
]);
yScale.domain([
d3.max(dataset_winner, function(d) {
return timeFormat.parse(d.ActualTime);
}),
d3.min(dataset_winner, function(d) {
return timeFormat.parse("00:00:00");
})
]);
//Lines
svg.data([ dataset_winner ])
.append("path")
.attr("class", "area winner")
.attr("d", area)
svg.data([ dataset_fastest ])
.append("path")
.attr("class", "line fastest actual")
.attr("d", line_actual);
svg.data([ dataset_winner ])
.append("path")
.attr("class", "line winner actual")
.attr("d", line_actual);
svg.data([ dataset_winner ])
.append("path")
.attr("class", "line winner clock")
.attr("d", line_clock);
//Line Labels
svg.append("text")
.attr("transform", "translate(" + ( w + 3 ) + ","
+ yScale(timeFormat.parse(dataset_fastest[dataset_fastest.length-1].ActualTime)) + ")")
.attr("dy", ".35em")
.attr("text-anchor", "start")
.attr("class", "linelabel fastest")
.text("Fastest Time");
svg.append("text")
.attr("transform", "translate(" + ( w + 3 ) + ","
+ yScale(timeFormat.parse(dataset_winner[dataset_winner.length-1].ActualTime)) + ")")
.attr("dy", ".35em")
.attr("text-anchor", "start")
.attr("class", "linelabel winner")
.text("Winner's Actual Time");
svg.append("text")
.attr("transform", "translate(" + ( w + 3 ) + ","
+ yScale(timeFormat.parse(dataset_winner[dataset_winner.length-1].ClockTime)) + ")")
.attr("dy", ".35em")
.attr("text-anchor", "start")
.attr("class", "linelabel winner")
.text("Winner's Net Time");
//Bind filtered data into rect placeholders
var dots = svg.selectAll("circle")
.data(dataset_winner)
.enter()
.append("circle");
//Set attributes of circles
dots.attr("cx", function(d) {
return xScale(yearFormat.parse(d.Year));
})
.attr("cy", function(d) {
return yScale(timeFormat.parse(d.ClockTime));
})
.attr("r", 2)
.attr("class", function(d) {
if (d.Sex == "M") { return "circle men";};
if (d.Sex == "F") { return "circle women";};
//else { return "circle"; };
})
.append("title")
.text(function(d) {
return "Sex: " + d.Sex + " Age: " + d.Age + " Head Start : " + d.HeadStart + " minutes";
});
//Append Axis titles
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + h + ")")
.call(xAxis)
.append("text")
.attr("transform", "rotate(0)")
.attr("y", 6)
.attr("dy", "3em")
.attr("dx", w)
.style("text-anchor", "end")
.style("font-weight", "bold")
.text("Year");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", "-6em")
.style("text-anchor", "end")
.style("font-weight", "bold")
.text("Time");
//Add grid lines
var yAxisGrid = yAxis.ticks(8)
.tickSize(w,0)
.tickFormat("")
.orient("right");
svg.append("g")
.classed('y', true)
.classed('grid', true)
.call(yAxisGrid);
});
</script>
</body>
</html>
Modified http://d3js.org/d3.v3.js to a secure url
https://d3js.org/d3.v3.js