Skip to content

Instantly share code, notes, and snippets.

@pmarshall111
Last active February 22, 2018 21:21
Show Gist options
  • Save pmarshall111/d6234abcc757237092815d3c5995537b to your computer and use it in GitHub Desktop.
Save pmarshall111/d6234abcc757237092815d3c5995537b to your computer and use it in GitHub Desktop.
Github Contributions Graph made with D3
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<style>
.tooltip {
position: absolute;
background: #333;
color: #ddd;
border: 3px solid #ddd;
border-radius: 2px;
pointer-events: none;
padding: 0.25em
}
.y-axis path {
transform: scaleY(1.5) translateY(-30%)
}
</style>
</head>
<script src="https://d3js.org/d3.v4.min.js"></script>
<body>
<svg height="300" width="900"></svg>
<script>
var testData = [];
for (var i = 1; i < 100; i++) {
var randomMonth = Math.floor(Math.random() * 12) + 1;
var randomDay = Math.floor(Math.random() * 28) + 1;
var randomNumb = Math.floor(Math.random() * 10);
var createdDate = new Date(`2018-${randomMonth}-${randomDay}`);
if (testData.filter(x => x.date == createdDate).length > 0) continue;
testData.push({
date: createdDate,
numb: randomNumb
});
}
//creating tooltip
var div = d3
.select("body")
.append("div")
.classed("tooltip", true)
.style("opacity", 0);
var svg = d3.select("svg");
var height = +svg.attr("height");
var width = +svg.attr("width");
var padding = 50;
var g = svg
.append("g")
.style("transform", `translate(${padding}px, ${padding}px)`);
var today = new Date();
var oneYearAgo = new Date();
oneYearAgo.setFullYear(oneYearAgo.getFullYear() - 1);
var cellSize = (width - padding * 2) / 53;
//setting positions of the ticks to be halfway between boundaries
var yAxisRange = [];
for (let i = 1; i < 7; i += 2) {
yAxisRange.push(cellSize / 2 + cellSize * i);
}
var yAxis = d3
.scaleOrdinal()
.range(yAxisRange)
.domain(["Mon", "Wed", "Fri"]);
var xAxis = d3
.scaleTime()
.range([0, width - padding * 2])
.domain([oneYearAgo, today]);
var xAxisLine = g
.append("g")
.style("transform", `translate(0px, ${cellSize * 8}px)`)
.call(d3.axisBottom(xAxis));
var yAxisLine = g
.append("g")
.style("transform", `translate(-${cellSize}px, 0px)`)
.classed("y-axis", true)
.call(d3.axisLeft(yAxis));
//adding extra ticks for Tuesday and Thursday
for (let y = 0; y < 2; y++) {
let g = yAxisLine
.append("g")
.classed("tick", true)
.attr("transform", `translate(0, ${cellSize * (2 + 2 * y) + cellSize / 2})`)
.attr("opacity", 1);
g
.append("line")
.attr("x2", -4)
.attr("stroke", "#000");
}
var rect = g
.selectAll("rect")
.data(d => d3.timeDays(oneYearAgo, today))
.enter()
.append("rect")
.attr("stroke", "black")
.attr("fill", "transparent")
.attr("width", cellSize)
.attr("height", cellSize)
.attr("x", function(d) {
//gets num weeks between one year ago and date of current rect
return d3.timeWeek.count(oneYearAgo, d) * cellSize;
})
.attr("y", function(d) {
return d.getDay() * cellSize;
})
.on("mouseover", function(d) {
var text = this.getAttribute("data-info");
if (!text) text = "0 contributions.";
div
.html(text)
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY - 32 + "px");
div
.transition()
.duration(100)
.style("opacity", 1);
})
.on("mouseout", d => {
div
.transition()
.duration(100)
.style("opacity", 0);
});
//adding colours
var maxMin = d3.extent(testData, x => x.numb);
var colours = new Array(5)
.fill("abc")
.map((x, i) => `hsl(60, ${100 * (5 - i) / 5}%, 50%)`);
var colourScale = d3
.scaleQuantize()
.domain(maxMin)
.range(colours);
testData.forEach(entry => {
var indiv = rect.filter(
d =>
d.getDate() == entry.date.getDate() &&
d.getMonth() == entry.date.getMonth()
);
indiv
.attr("fill", colourScale(entry.numb))
.attr("data-info", `${entry.numb} contributions.`);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment