Skip to content

Instantly share code, notes, and snippets.

@thebenedict
Created October 24, 2014 15:14
Show Gist options
  • Save thebenedict/8467a4180bae71316e93 to your computer and use it in GitHub Desktop.
Save thebenedict/8467a4180bae71316e93 to your computer and use it in GitHub Desktop.
Weekly Commits
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
h3 { margin: 0.25em 0; }
h5 {
font-style: italic;
font-weight: 400;
margin: 0.25em 0;
color: #aaa;
}
.header {
margin-left: 17px;
}
.sort-label { font-weight: 600; }
.sort { font-size: 0.83em; }
</style>
<body>
<div class="header">
<h3>Weekly commits to mbostock/d3 for the past year</h3>
<h5>hover over circles for commit counts</h5>
<div class="sort">
<span class="sort-label">Sort</span>
<input name="sort-mode" type="radio" value="chron" id="sort-chron" checked><label for="horizon-mode-offset"> chronological</label>
<input name="sort-mode" type="radio" value="count" id="sort-count"><label for="sort-count"> commit count</label>
</div>
</div>
<svg width="960" height="500"></svg>
</body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/moment.js/2.8.3/moment.min.js"></script>
<script>
var url = "https://api.github.com/repos/mbostock/d3/stats/commit_activity";
var data;
var ROW_LEN = 10;
var GRID_SIZE = 70;
var MARGIN = 50;
var RECT_SIZE = 67;
function circleY(i) { return Math.ceil((i + 1) / ROW_LEN) * GRID_SIZE - RECT_SIZE / 2; }
function circleX(i) { return i % ROW_LEN * GRID_SIZE + MARGIN; }
d3.json(url, function(error, json) {
if (error) return console.warn(error);
data = json;
drawCircles(data);
});
function drawCircles(data) {
var svg = d3.select("svg");
svg.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("y", function(d, i) { return Math.ceil((i + 1) / ROW_LEN) * GRID_SIZE - RECT_SIZE; })
.attr("x", function(d, i) { return i % ROW_LEN * GRID_SIZE + MARGIN - RECT_SIZE / 2; })
.attr("width", RECT_SIZE)
.attr("height", RECT_SIZE)
.style('fill', 'rgba(236, 240, 241, 1.0)');
svg.selectAll("circle")
.data(data)
.enter().append("circle")
.attr("cy", function(d, i) { return circleY(i) })
.attr("cx", function(d, i) { return circleX(i) })
.attr("r", function(d) { return getScaledValue(d.total) })
.style('fill', 'rgba(231, 76, 60,1.0)')
.append("title").text(function(d) { return formatTitle(d.total, d.week); });
}
// format title strings for tooltips
function formatTitle(commitCount, timestamp) {
var weekStart = moment.unix(timestamp).format("MMM Do");
return "Week of " + weekStart + "\nCommits: " + commitCount;
}
// scale circle radii so small values are visible
function getScaledValue(commitCount) {
if (commitCount) { return commitCount * 1.4 + (20 - commitCount) / 5; }
else { return 0; }
}
d3.selectAll("input[name=sort-mode]").on("change", function() {
change(this.value)
});
function change(mode) {
mode === "count"
? data.sort(function(a, b) { return d3.descending(a.total, b.total); })
: data.sort(function(a, b) { return d3.ascending(a.week, b.week); });
// find the new position of a week in the sorted data
sorted = function(week) {
var idx;
data.forEach(function(d, i) {
if (d.week === week) idx = i;
});
return idx;
};
// transition circle positions over 1 second
var svg = d3.select("svg");
var transition = svg.transition().duration(1000)
transition.selectAll("circle")
.attr("cy", function(d) { return circleY(sorted(d.week)); })
.attr("cx", function(d) { return circleX(sorted(d.week)); })
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment