Skip to content

Instantly share code, notes, and snippets.

@simple10
Forked from harlantwood/circle-packing.coffee
Last active December 14, 2015 00:59
Show Gist options
  • Save simple10/5002941 to your computer and use it in GitHub Desktop.
Save simple10/5002941 to your computer and use it in GitHub Desktop.
Github D3 Visualizer
root = exports ? this
class root.App
constructor: (repo) ->
@github = new App.Github
@d3 = new App.D3
@github.loadRepo(repo, (data) =>
data = @github.parseForD3(data)
@d3.renderCirclePack(data)
) if repo
root = exports ? this
class root.App.D3
renderCirclePack: (data) ->
width = 600
height = 600
format = d3.format(",d")
pack = d3.layout.pack()
.size([ width - 4, height - 4 ])
.value((d) -> d.size)
vis = d3.select("#viz-collections").append("svg")
.attr("width", width)
.attr("height", height)
.attr("class", "pack")
.append("g")
.attr("transform", "translate(2, 2)")
node = vis.data([ data ]).selectAll("#viz-collections g.node")
.data(pack.nodes)
.enter().append("g")
.attr("class", (d) -> if d.children then "node" else "leaf node")
.attr("transform", (d) -> "translate(" + d.x + "," + d.y + ")")
node.append("title")
.text (d) -> d.name + (if d.children then "" else ": " + format(d.size))
node.append("circle")
.attr("r", (d) -> d.r)
.on "click", (d) -> if d.children then (window.location = d.url) else undefined
node.filter((d) -> d.children)
.append("text")
.attr("text-anchor", "middle")
.attr("dy", ".3em")
.text (d) -> if d.name.length <= d.r/3 then d.name else ""
// Generated by CoffeeScript 1.4.0
(function() {
var root;
root = typeof exports !== "undefined" && exports !== null ? exports : this;
root.App.D3 = (function() {
function D3() {}
D3.prototype.renderCirclePack = function(data) {
var format, height, node, pack, vis, width;
width = 600;
height = 600;
format = d3.format(",d");
pack = d3.layout.pack().size([width - 4, height - 4]).value(function(d) {
return d.size;
});
vis = d3.select("#viz-collections").append("svg").attr("width", width).attr("height", height).attr("class", "pack").append("g").attr("transform", "translate(2, 2)");
node = vis.data([data]).selectAll("#viz-collections g.node").data(pack.nodes).enter().append("g").attr("class", function(d) {
if (d.children) {
return "node";
} else {
return "leaf node";
}
}).attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
node.append("title").text(function(d) {
return d.name + (d.children ? "" : ": " + format(d.size));
});
node.append("circle").attr("r", function(d) {
return d.r;
}).on("click", function(d) {
if (d.children) {
return window.location = d.url;
} else {
return void 0;
}
});
return node.filter(function(d) {
return d.children;
}).append("text").attr("text-anchor", "middle").attr("dy", ".3em").text(function(d) {
if (d.name.length <= d.r / 3) {
return d.name;
} else {
return "";
}
});
};
return D3;
})();
}).call(this);
root = exports ? this
class root.App.Github
loadRepo: (repo, success, error, recursive = true) ->
$.get("https://api.github.com/repos/#{repo}/git/trees/HEAD?recursive=#{if recursive then '1' else '0'}", success)
parseForD3: (data) ->
tree = data.tree
paths = {}
for node in tree
continue if node.type == 'tree'
segments = "root/#{node.path}".match(/(.*)\/(.*)/)
file = segments[2]
path = segments[1]
paths[path] ||=
name: path.substr(5)
children: []
node.name = file
paths[path].children.push(node)
for path, node of paths
parent = path.match(/(.*)\/(.*)/)
continue unless parent && parent = parent[1]
paths[parent] ||= {
name: path
children: []
}
paths[parent].children.push(node)
paths.root
// Generated by CoffeeScript 1.4.0
(function() {
var root;
root = typeof exports !== "undefined" && exports !== null ? exports : this;
root.App.Github = (function() {
function Github() {}
Github.prototype.loadRepo = function(repo, success, error, recursive) {
if (recursive == null) {
recursive = true;
}
return $.get("https://api.github.com/repos/" + repo + "/git/trees/HEAD?recursive=" + (recursive ? '1' : '0'), success);
};
Github.prototype.parseForD3 = function(data) {
var file, node, parent, path, paths, segments, tree, _i, _len;
tree = data.tree;
paths = {};
for (_i = 0, _len = tree.length; _i < _len; _i++) {
node = tree[_i];
if (node.type === 'tree') {
continue;
}
segments = ("root/" + node.path).match(/(.*)\/(.*)/);
file = segments[2];
path = segments[1];
paths[path] || (paths[path] = {
name: path.substr(5),
children: []
});
node.name = file;
paths[path].children.push(node);
}
for (path in paths) {
node = paths[path];
parent = path.match(/(.*)\/(.*)/);
if (!(parent && (parent = parent[1]))) {
continue;
}
paths[parent] || (paths[parent] = {
name: path,
children: []
});
paths[parent].children.push(node);
}
return paths.root;
};
return Github;
})();
}).call(this);
// Generated by CoffeeScript 1.4.0
(function() {
var root;
root = typeof exports !== "undefined" && exports !== null ? exports : this;
root.App = (function() {
function App(repo) {
var _this = this;
this.github = new App.Github;
this.d3 = new App.D3;
if (repo) {
this.github.loadRepo(repo, function(data) {
data = _this.github.parseForD3(data);
return _this.d3.renderCirclePack(data);
});
}
}
return App;
})();
}).call(this);
# Sinatra app for local development
# $ ruby app.rb
require 'rubygems'
require 'sinatra'
set :static, true
set :public_folder, './'
get '/' do
redirect '/index.html'
end
circle {
fill-opacity: .25;
stroke-width: 1px;
fill: #1f77b4;
stroke: steelblue;
}
.leaf circle {
fill-opacity: 0;
pointer-events: none;
}
text {
font: 12px sans-serif;
}
.leaf text {
opacity: 0;
}
text.parent {
fill: #1f77b4;
}
circle.parent:hover {
stroke: #ff7f0e;
stroke-width: .5px;
}
<!DOCTYPE html>
<html>
<head>
<title>Github Visualizer</title>
<link href="circle-packing.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="viz-collections"></div>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="//d3js.org/d3.v3.min.js"></script>
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="app.d3.js"></script>
<script type="text/javascript" src="app.github.js"></script>
<script>
new App('rails/rails');
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment