This example builds a heatmap calendar with vertical weeks instead of the horizontal weeks in Calendar heatmap (horizontal). See also Mike Bostock's Calendar View.
Last active
January 25, 2019 21:11
-
-
Save danbjoseph/13d9365450c27ed3bf5a568721296dcc to your computer and use it in GitHub Desktop.
Calendar heat map (vertical)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: gpl-3.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
day | count | |
---|---|---|
2016-05-12 | 171 | |
2016-06-17 | 139 | |
2016-05-02 | 556 | |
2016-04-10 | 1 | |
2016-05-04 | 485 | |
2016-03-27 | 1 | |
2016-05-26 | 42 | |
2016-05-25 | 337 | |
2016-05-23 | 267 | |
2016-05-05 | 569 | |
2016-03-31 | 32 | |
2016-03-25 | 128 | |
2016-05-13 | 221 | |
2016-03-30 | 26 | |
2016-03-15 | 3 | |
2016-04-24 | 10 | |
2016-04-27 | 312 | |
2016-03-20 | 99 | |
2016-05-10 | 358 | |
2016-04-01 | 15 | |
2016-05-11 | 199 | |
2016-07-06 | 744 | |
2016-05-08 | 23 | |
2016-03-28 | 98 | |
2016-03-29 | 64 | |
2016-04-30 | 152 | |
2016-03-21 | 148 | |
2016-03-19 | 20 | |
2016-05-07 | 69 | |
2016-04-29 | 431 | |
2016-04-25 | 330 | |
2016-04-28 | 353 | |
2016-04-18 | 9 | |
2016-01-10 | 1 | |
2016-01-09 | 2 | |
2016-03-26 | 21 | |
2016-05-27 | 18 | |
2016-04-19 | 10 | |
2016-04-06 | 1 | |
2016-04-12 | 214 | |
2016-05-03 | 536 | |
2016-07-03 | 3 | |
2016-06-16 | 1 | |
2016-03-24 | 138 | |
2016-04-26 | 351 | |
2016-04-23 | 14 | |
2016-05-01 | 19 | |
2016-07-05 | 523 | |
2016-05-22 | 3 | |
2016-05-09 | 430 | |
2016-05-24 | 472 | |
2016-04-11 | 172 | |
2016-03-17 | 7 | |
2016-05-14 | 10 | |
2016-05-06 | 449 | |
2016-07-04 | 295 | |
2016-05-15 | 12 | |
2016-03-23 | 216 | |
2016-03-18 | 47 | |
2016-03-22 | 179 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
#calendar { | |
margin: 20px; | |
} | |
.month { | |
margin-right: 8px; | |
} | |
.month-name { | |
font-size: 85%; | |
fill: #777; | |
font-family: Arial, Helvetica; | |
} | |
.day.hover { | |
stroke: #6d6E70; | |
stroke-width: 2; | |
} | |
.day.focus { | |
stroke: #ffff33; | |
stroke-width: 2; | |
} | |
</style> | |
<body> | |
<div id="calendar"></div> | |
<script src="//d3js.org/d3.v4.min.js"></script> | |
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script> | |
<script> | |
function drawCalendar(dateData){ | |
var weeksInMonth = function(month){ | |
var m = d3.timeMonth.floor(month) | |
return d3.timeWeeks(d3.timeWeek.floor(m), d3.timeMonth.offset(m,1)).length; | |
} | |
var minDate = d3.min(dateData, function(d) { return new Date(d.day) }) | |
var maxDate = d3.max(dateData, function(d) { return new Date(d.day) }) | |
var cellMargin = 2, | |
cellSize = 20; | |
var day = d3.timeFormat("%w"), | |
week = d3.timeFormat("%U"), | |
format = d3.timeFormat("%Y-%m-%d"), | |
titleFormat = d3.utcFormat("%a, %d-%b"); | |
monthName = d3.timeFormat("%B"), | |
months= d3.timeMonth.range(d3.timeMonth.floor(minDate), maxDate); | |
var svg = d3.select("#calendar").selectAll("svg") | |
.data(months) | |
.enter().append("svg") | |
.attr("class", "month") | |
.attr("height", ((cellSize * 7) + (cellMargin * 8) + 20) ) // the 20 is for the month labels | |
.attr("width", function(d) { | |
var columns = weeksInMonth(d); | |
return ((cellSize * columns) + (cellMargin * (columns + 1))); | |
}) | |
.append("g") | |
svg.append("text") | |
.attr("class", "month-name") | |
.attr("y", (cellSize * 7) + (cellMargin * 8) + 15 ) | |
.attr("x", function(d) { | |
var columns = weeksInMonth(d); | |
return (((cellSize * columns) + (cellMargin * (columns + 1))) / 2); | |
}) | |
.attr("text-anchor", "middle") | |
.text(function(d) { return monthName(d); }) | |
var rect = svg.selectAll("rect.day") | |
.data(function(d, i) { return d3.timeDays(d, new Date(d.getFullYear(), d.getMonth()+1, 1)); }) | |
.enter().append("rect") | |
.attr("class", "day") | |
.attr("width", cellSize) | |
.attr("height", cellSize) | |
.attr("rx", 3).attr("ry", 3) // rounded corners | |
.attr("fill", '#eaeaea') // default light grey fill | |
.attr("y", function(d) { return (day(d) * cellSize) + (day(d) * cellMargin) + cellMargin; }) | |
.attr("x", function(d) { return ((week(d) - week(new Date(d.getFullYear(),d.getMonth(),1))) * cellSize) + ((week(d) - week(new Date(d.getFullYear(),d.getMonth(),1))) * cellMargin) + cellMargin ; }) | |
.on("mouseover", function(d) { | |
d3.select(this).classed('hover', true); | |
}) | |
.on("mouseout", function(d) { | |
d3.select(this).classed('hover', false); | |
}) | |
.datum(format); | |
rect.append("title") | |
.text(function(d) { return titleFormat(new Date(d)); }); | |
var lookup = d3.nest() | |
.key(function(d) { return d.day; }) | |
.rollup(function(leaves) { | |
return d3.sum(leaves, function(d){ return parseInt(d.count); }); | |
}) | |
.object(dateData); | |
var scale = d3.scaleLinear() | |
.domain(d3.extent(dateData, function(d) { return parseInt(d.count); })) | |
.range([0.4,1]); // the interpolate used for color expects a number in the range [0,1] but i don't want the lightest part of the color scheme | |
rect.filter(function(d) { return d in lookup; }) | |
.style("fill", function(d) { return d3.interpolatePuBu(scale(lookup[d])); }) | |
.select("title") | |
.text(function(d) { return titleFormat(new Date(d)) + ": " + lookup[d]; }); | |
} | |
d3.csv("dates.csv", function(response){ | |
drawCalendar(response); | |
}) | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment