Skip to content

Instantly share code, notes, and snippets.

@danbjoseph
Last active June 27, 2019 18:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danbjoseph/3f42bb3f0ab6133cfc192e878c9030ed to your computer and use it in GitHub Desktop.
Save danbjoseph/3f42bb3f0ab6133cfc192e878c9030ed to your computer and use it in GitHub Desktop.
Calendar heat map (horizontal)
license: gpl-3.0
<!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="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script>
function drawCalendar(myData) {
var calendarRows = 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(myData, function(d) { return new Date(d.submissionTime); });
var maxDate = d3.max(myData, function(d) { return new Date(d.submissionTime); });
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);
for(var i=0; i<myData.length; i++){
myData[i].today = myData[i].submissionTime.slice(0,10);
}
var svg = d3.select("#calendar").selectAll("svg")
.data(months)
.enter().append("svg")
.attr("class", "month")
.attr("width", (cellSize * 7) + (cellMargin * 8) )
.attr("height", function(d) {
var rows = calendarRows(d);
return (cellSize * rows) + (cellMargin * (rows + 1)) + 20; // the 20 is for the month labels
})
.append("g")
svg.append("text")
.attr("class", "month-name")
.attr("x", ((cellSize * 7) + (cellMargin * 8)) / 2 )
.attr("y", 15)
.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("x", function(d) {
return (day(d) * cellSize) + (day(d) * cellMargin) + cellMargin;
})
.attr("y", 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 + 20;
})
.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.today; })
.rollup(function(leaves) { return leaves.length; })
.object(myData);
count = d3.nest()
.key(function(d) { return d.today; })
.rollup(function(leaves) { return leaves.length; })
.entries(myData);
scale = d3.scaleLinear()
.domain(d3.extent(count, function(d) { return d.value; }))
.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])); })
.classed("clickable", true)
.on("click", function(d){
if(d3.select(this).classed('focus')){
d3.select(this).classed('focus', false);
} else {
d3.select(this).classed('focus', true)
}
// doSomething();
})
.select("title")
.text(function(d) { return titleFormat(new Date(d)) + ": " + lookup[d]; });
}
d3.csv("submissions.csv", function(response) {
drawCalendar(response);
})
</script>
</body>
We can make this file beautiful and searchable if this error is corrected: No commas found in this CSV file in line 0.
submissionTime
2017-09-27T16:21:13.988Z
2017-09-27T16:21:10.444Z
2017-09-27T16:21:04.537Z
2017-09-28T17:51:19.026Z
2017-09-28T17:51:13.704Z
2017-09-28T17:51:59.180Z
2017-09-28T17:51:36.288Z
2017-09-28T17:51:41.993Z
2017-09-28T17:51:24.239Z
2017-09-28T17:51:45.261Z
2017-09-28T17:51:05.595Z
2017-09-28T17:51:28.132Z
2017-09-28T17:51:04.410Z
2017-09-28T17:51:10.971Z
2017-09-28T17:51:55.169Z
2017-09-28T17:51:50.099Z
2017-09-28T17:51:07.970Z
2017-09-28T17:51:34.015Z
2017-09-28T17:51:52.889Z
2017-09-28T17:51:22.374Z
2017-09-28T17:51:16.294Z
2017-09-28T17:51:39.297Z
2017-09-28T17:51:31.607Z
2017-09-28T17:51:20.837Z
2017-09-28T17:52:01.266Z
2017-09-29T15:54:18.410Z
2017-09-29T15:54:23.104Z
2017-09-29T15:54:29.337Z
2017-09-29T15:54:33.397Z
2017-09-29T15:54:35.060Z
2017-09-29T15:54:36.959Z
2017-09-29T16:47:02.481Z
2017-09-29T16:47:03.662Z
2017-09-29T16:47:04.464Z
2017-10-03T17:00:56.188Z
2017-10-03T17:00:57.605Z
2017-10-03T17:00:58.574Z
2017-10-03T17:00:59.833Z
2017-10-03T17:01:00.882Z
2017-10-03T17:01:04.374Z
2017-10-03T17:01:05.606Z
2017-10-03T17:01:41.907Z
2017-10-04T16:32:38.787Z
2017-10-04T16:32:41.320Z
2017-10-04T16:32:43.936Z
2017-10-04T16:32:51.535Z
2017-10-04T16:32:57.178Z
2017-10-04T16:32:59.446Z
2017-10-04T16:33:02.290Z
2017-10-04T16:33:07.605Z
2017-10-04T16:33:21.245Z
2017-10-04T16:33:21.404Z
2017-10-04T16:33:28.446Z
2017-10-04T16:33:34.599Z
2017-10-04T16:33:40.175Z
2017-10-04T16:33:42.479Z
2017-10-04T16:33:46.558Z
2017-10-04T16:33:51.701Z
2017-10-04T16:33:56.583Z
2017-10-04T16:34:10.091Z
2017-10-04T16:34:10.216Z
2017-10-04T16:34:15.977Z
2017-10-04T16:34:20.967Z
2017-10-04T16:34:26.459Z
2017-10-04T16:34:32.806Z
2017-10-04T16:34:33.428Z
2017-10-04T16:34:34.825Z
2017-10-04T16:34:41.896Z
2017-10-04T16:34:50.728Z
2017-10-04T16:35:06.723Z
2017-09-27T16:21:13.988Z
2017-09-27T16:21:10.444Z
2017-09-27T16:21:04.537Z
2017-09-28T17:51:19.026Z
2017-09-28T17:51:13.704Z
2017-09-28T17:51:59.180Z
2017-09-28T17:51:36.288Z
2017-09-28T17:51:41.993Z
2017-09-28T17:51:24.239Z
2017-09-28T17:51:45.261Z
2017-09-28T17:51:05.595Z
2017-09-28T17:51:28.132Z
2017-09-28T17:51:04.410Z
2017-09-28T17:51:10.971Z
2017-09-28T17:51:55.169Z
2017-09-28T17:51:50.099Z
2017-09-28T17:51:07.970Z
2017-09-28T17:51:34.015Z
2017-09-28T17:51:52.889Z
2017-09-28T17:51:22.374Z
2017-09-28T17:51:16.294Z
2017-09-28T17:51:39.297Z
2017-09-28T17:51:31.607Z
2017-09-28T17:51:20.837Z
2017-09-28T17:52:01.266Z
2017-09-29T15:54:18.410Z
2017-09-29T15:54:23.104Z
2017-09-29T15:54:29.337Z
2017-09-29T15:54:33.397Z
2017-09-29T15:54:35.060Z
2017-09-29T15:54:36.959Z
2017-09-29T16:47:02.481Z
2017-09-29T16:47:03.662Z
2017-09-29T16:47:04.464Z
2017-11-05T17:00:56.188Z
2017-11-05T17:00:57.605Z
2017-11-05T17:00:58.574Z
2017-11-05T17:00:59.833Z
2017-11-05T17:01:00.882Z
2017-11-05T17:01:04.374Z
2017-11-05T17:01:05.606Z
2017-11-05T17:01:41.907Z
2017-10-18T16:32:38.787Z
2017-10-18T16:32:41.320Z
2017-10-18T16:32:43.936Z
2017-10-18T16:32:51.535Z
2017-10-18T16:32:57.178Z
2017-10-18T16:32:59.446Z
2017-10-18T16:33:02.290Z
2017-10-18T16:33:07.605Z
2017-10-18T16:33:21.245Z
2017-10-18T16:33:21.404Z
2017-10-18T16:33:28.446Z
2017-10-18T16:33:34.599Z
2017-10-18T16:33:40.175Z
2017-10-18T16:33:42.479Z
2017-10-18T16:33:46.558Z
2017-10-18T16:33:51.701Z
2017-10-18T16:33:56.583Z
2017-10-18T16:34:10.091Z
2017-10-18T16:34:10.216Z
2017-10-18T16:34:15.977Z
2017-10-18T16:34:20.967Z
2017-10-18T16:34:26.459Z
2017-10-18T16:34:32.806Z
2017-10-18T16:34:33.428Z
2017-10-18T16:34:34.825Z
2017-10-18T16:34:41.896Z
2017-10-18T16:34:50.728Z
2017-10-18T16:35:06.723Z
2017-10-19T16:21:13.988Z
2017-10-19T16:21:10.444Z
2017-10-19T16:21:04.537Z
2017-10-16T17:51:19.026Z
2017-10-16T17:51:13.704Z
2017-10-16T17:51:59.180Z
2017-10-16T17:51:36.288Z
2017-10-16T17:51:41.993Z
2017-10-16T17:51:24.239Z
2017-10-16T17:51:45.261Z
2017-10-16T17:51:05.595Z
2017-10-16T17:51:28.132Z
2017-10-16T17:51:04.410Z
2017-10-16T17:51:10.971Z
2017-10-16T17:51:39.297Z
2017-10-16T17:51:31.607Z
2017-10-16T17:51:20.837Z
2017-10-16T17:52:01.266Z
2017-11-06T15:54:18.410Z
2017-11-06T15:54:23.104Z
2017-11-06T15:54:29.337Z
2017-11-06T15:54:33.397Z
2017-11-06T15:54:35.060Z
2017-11-06T15:54:36.959Z
2017-11-06T16:47:02.481Z
2017-11-06T16:47:03.662Z
2017-11-06T16:47:04.464Z
2017-11-08T17:00:56.188Z
2017-11-08T17:00:57.605Z
2017-11-08T17:00:58.574Z
2017-11-08T17:00:59.833Z
2017-11-08T17:01:00.882Z
2017-11-08T17:01:04.374Z
2017-11-08T17:01:05.606Z
2017-11-08T17:01:41.907Z
2017-10-09T16:32:38.787Z
2017-10-09T16:32:41.320Z
2017-10-09T16:32:43.936Z
2017-10-09T16:32:51.535Z
2017-10-09T16:32:57.178Z
2017-10-09T16:32:59.446Z
2017-10-09T16:33:02.290Z
2017-10-09T16:33:07.605Z
2017-10-09T16:33:21.245Z
2017-10-09T16:33:21.404Z
2017-10-09T16:33:28.446Z
2017-10-09T16:33:34.599Z
2017-10-09T16:33:40.175Z
2017-10-09T16:33:42.479Z
2017-10-09T16:33:46.558Z
2017-10-09T16:33:51.701Z
2017-10-09T16:33:56.583Z
2017-10-09T16:34:10.091Z
2017-10-09T16:34:10.216Z
2017-10-09T16:34:15.977Z
2017-10-09T16:34:20.967Z
2017-10-09T16:34:26.459Z
2017-10-09T16:34:32.806Z
2017-10-09T16:34:33.428Z
2017-10-09T16:34:34.825Z
2017-10-09T16:34:41.896Z
2017-10-09T16:34:50.728Z
2017-10-09T16:35:06.723Z
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment