|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style type="text/css"> |
|
.day { fill: #fff; stroke: #ccc;} |
|
.month { fill: none; stroke: #000; stroke-width: 2px;} |
|
.RdYlGn .q8-11{fill:#4D004B} |
|
.RdYlGn .q7-11{fill:#810F7C} |
|
.RdYlGn .q6-11{fill:#88419D} |
|
.RdYlGn .q5-11{fill:#8C6BB1} |
|
.RdYlGn .q4-11{fill:#8C96C6} |
|
.RdYlGn .q3-11{fill:#9EBCDA} |
|
.RdYlGn .q2-11{fill:#BFD3E6} |
|
.RdYlGn .q1-11{fill:#E0ECF4} |
|
.RdYlGn .q0-11{fill:#F7FCFD} |
|
</style> |
|
<body> |
|
<div id="calendar"></div> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
<script type="text/javascript"> |
|
//constants |
|
var width = 960, |
|
height = 136, |
|
cellsize = 17; |
|
//value formatting |
|
var day = d3.time.format('%w'), |
|
week = d3.time.format('%U'), |
|
percent = d3.format(".1%"), |
|
format = d3.time.format('%Y-%m-%d'); |
|
//calcs |
|
var color = d3.scale.quantize() |
|
.domain([8.8, 45.7]) |
|
.range(d3.range(9).map(function(d) { |
|
return 'q' + d + '-11'; |
|
})); |
|
|
|
//Create svg container and g for each year |
|
var svg = d3.select('#calendar') |
|
.selectAll('svg') |
|
.data(d3.range(2002, 2013)) |
|
.enter() |
|
.append('svg') |
|
.attr('width', width) |
|
.attr('height', height) |
|
.attr("class", "RdYlGn") |
|
.append('g') |
|
.attr('transform', 'translate(' + ((width - cellsize * 53) / 2) + ',' + (height - cellsize * 7 - 1) + ')'); |
|
|
|
//Add text labels for each year |
|
svg.append('text') |
|
.attr('transform', 'translate(-6,' + cellsize * 3.5 + ')rotate(-90)') |
|
.style('text-anchor', 'middle') |
|
.text(function(d) { return d; }); //d represents the data bound to the element, which is the year |
|
|
|
//Add the day cells |
|
var rect = svg.selectAll('.day') |
|
//days between the first of the year and first of following year |
|
.data(function(d) { return d3.time.days(new Date(d, 0, 1), new Date(d+1, 0, 1)); }) |
|
.enter().append('rect') |
|
.attr('class', 'day') |
|
.attr('width', cellsize) |
|
.attr('height', cellsize) |
|
.attr('x', function(d) { return week(d) * cellsize; }) |
|
.attr('y', function(d) { return day(d) * cellsize; }) |
|
.datum(format); |
|
|
|
//Add a title element to the rect with the current date |
|
rect.append('title') |
|
.text(function(d) { return d; }); |
|
|
|
//add months |
|
svg.selectAll('.month') |
|
.data(function(d) { return d3.time.months(new Date(d, 0, 1), new Date(d+1, 0, 1)); }) |
|
.enter().append('path') |
|
.attr('class', 'month') |
|
.attr('d', monthPath); |
|
|
|
//add data |
|
d3.csv('temperature.csv', function(error, csv){ |
|
var data = d3.nest() |
|
.key(function(d) { |
|
return d.Year + '-' + d.Month + '-' + d.Day; |
|
}) |
|
.map(csv); |
|
rect.filter(function(d) { return d in data; }) |
|
.attr("class", function(d) { |
|
return "day " + color(data[d][0]['Maximum temperature (Degree C)']); |
|
}) |
|
.select("title") |
|
.text(function(d) { |
|
return d + ": " + data[d][0]['Maximum temperature (Degree C)'] + '°C'; |
|
}); |
|
}) |
|
|
|
//calculate month boundaries |
|
function monthPath(t0) { |
|
var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0), |
|
d0 = +day(t0), w0 = +week(t0), |
|
d1 = +day(t1), w1 = +week(t1); |
|
return "M" + (w0 + 1) * cellsize + "," + d0 * cellsize |
|
+ "H" + w0 * cellsize + "V" + 7 * cellsize |
|
+ "H" + w1 * cellsize + "V" + (d1 + 1) * cellsize |
|
+ "H" + (w1 + 1) * cellsize + "V" + 0 |
|
+ "H" + (w0 + 1) * cellsize + "Z"; |
|
} |
|
</script> |
|
</body> |