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