Skip to content

Instantly share code, notes, and snippets.

@pcarolan
Last active October 7, 2016 23:25
Show Gist options
  • Save pcarolan/8546e6c2953dd4c71ad35a908f988d07 to your computer and use it in GitHub Desktop.
Save pcarolan/8546e6c2953dd4c71ad35a908f988d07 to your computer and use it in GitHub Desktop.
Calendar Graph
[
{"created_at": "2016-10-06T16:22:24.520Z"},
{"created_at": "2016-10-05T16:24:39.039Z"},
{"created_at": "2016-10-04T16:24:39.039Z"},
{"created_at": "2016-10-02T16:24:39.039Z"},
{"created_at": "2016-10-01T16:24:39.039Z"},
{"created_at": "2016-09-25T16:24:39.039Z"},
{"created_at": "2016-09-24T16:24:39.039Z"},
{"created_at": "2016-09-23T16:24:39.039Z"},
{"created_at": "2016-09-22T16:24:39.039Z"},
{"created_at": "2016-09-21T16:24:39.039Z"},
{"created_at": "2016-09-20T16:24:39.039Z"},
{"created_at": "2016-09-06T16:24:39.039Z"},
{"created_at": "2016-09-05T16:24:39.039Z"},
{"created_at": "2016-10-04T16:24:39.039Z"},
{"created_at": "2016-10-03T16:24:39.039Z"},
{"created_at": "2016-10-02T16:24:39.039Z"},
{"created_at": "2016-10-01T16:24:39.039Z"},
{"created_at": "2016-09-01T16:24:39.039Z"},
{"created_at": "2016-08-01T16:24:39.039Z"},
{"created_at": "2016-07-01T16:24:39.039Z"},
{"created_at": "2016-06-01T16:24:39.039Z"},
{"created_at": "2016-05-01T16:24:39.039Z"},
{"created_at": "2016-04-01T16:24:39.039Z"},
{"created_at": "2016-03-01T16:24:39.039Z"},
{"created_at": "2016-02-01T16:24:39.039Z"},
{"created_at": "2016-01-01T16:24:39.039Z"},
{"created_at": "2015-12-01T16:24:39.039Z"},
{"created_at": "2015-11-01T16:24:39.039Z"}
]
function calendarGraph() {
class Grid {
constructor(x, y) {
this.x = x;
this.y = y;
}
build() {
let a = [];
for (let i = 0; i < this.x; i++) {
for (let j = 0; j < this.y; j++) {
a.push({
"x": i,
"y": j
});
}
}
return a;
}
}
grid = new Grid(52, 7);
var margin = {
top: 200,
right: 30,
bottom: 220,
left: 30
};
var width = 660 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svg = d3.select('body')
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// origin is top right because everything goes backwards and down.
var xScale = d3.scaleLinear().domain([1, grid.x]).range([width, 0]);
var yScale = d3.scaleLinear().domain([1, grid.y]).range([0, height]);
var xMap = function(d) {
return xScale(d.x)
};
var yMap = function(d) {
return yScale(d.y)
};
dateParser = d3.utcParse("%Y-%m-%dT%H:%M:%S.%LZ");
weekParser = d3.timeFormat('%U');
function weeksAgo(rawDate) {
return d3.timeWeek.count(dateParser(rawDate), new Date)
}
// draw the base grid
svg.selectAll("rect")
.data(grid.build())
.enter()
.append("rect")
.attr("stroke", "lightgrey")
.attr("fill", "none")
.attr("width", 10)
.attr("height", 10)
.attr("x", xMap)
.attr("y", yMap)
.append("svg:title")
.text(function(d) {
return d.x + "," + d.y;
});
// days of the week axis
dayLabels = [{'x': 53, 'y': 1, 'label': 'Mon'},
{'x': 53, 'y': 3, 'label': 'Wed'},
{'x': 53, 'y': 5, 'label': 'Fri'}]
var yLabels = svg.selectAll("text")
.data(dayLabels)
.enter();
yLabels.append("text")
.attr("x", xMap)
.attr("y", yMap)
.attr("font-size", ".5em")
.attr("font-family", "Helvetica")
.attr("fill","grey")
.attr("dy", "8.5px")
.text(function(d){return d.label;})
// month of year axis
today = d3.timeWeek.offset(new Date(), -0)
aYearAgo = d3.timeWeek.offset(new Date(), -52)
var xLabelScale = d3.scaleTime()
.domain([aYearAgo, today])
.range([0, width]);
var xAxis = d3.axisBottom()
.scale(xLabelScale)
.tickSize(0, 0)
.tickFormat(d3.timeFormat("%b"));
xAxisG = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + -35 + ")")
.call(xAxis)
xAxisG.selectAll(".tick text")
.style("text-anchor", "start")
.attr("fill","grey")
.attr("x", 6)
.attr("y", 6);
xAxisG.selectAll(".axis path")
.style("stroke", "none")
d3.json("activity.json", function(measurements) {
for (i = 0; i < measurements.length; i++) {
measurements[i]['day_of_week'] = dateParser(measurements[i]['created_at']).getDay();
measurements[i]['week_of_year'] = parseInt(weekParser(dateParser(measurements[i]['created_at'])));
measurements[i]['y'] = measurements[i]['day_of_week'];
measurements[i]['x'] = weeksAgo(measurements[i]['created_at']);
}
svg.selectAll('rect')
.data(measurements, function(d) {
return d.x + "," + d.y;
})
.attr("stroke", "lightgrey")
.attr("fill", "#AAF2D7")
// don't show days that are in the future.
var noDays = []
for (i = 6; i > (new Date).getDay(); i--) {
noDays.push({
"x": 0,
"y": i
})
}
svg.selectAll('rect')
.data(noDays, function(d) {
return d.x + "," + d.y;
})
.attr("fill", "none")
});
}
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="calendarGraph.js"></script>
<script type="text/javascript">calendarGraph()</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment