Skip to content

Instantly share code, notes, and snippets.

@splarty
Last active August 3, 2016 20:10
Show Gist options
  • Save splarty/7fb9b9db4ae0e0d1fe341512f1f3ed05 to your computer and use it in GitHub Desktop.
Save splarty/7fb9b9db4ae0e0d1fe341512f1f3ed05 to your computer and use it in GitHub Desktop.
circlePacking_II_d3.js
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<script type="text/javascript" src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/565729/underscore-min.js">
</script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<style>
body {
width: 100vw;
height: 100vh;
text-align: center;
}
#container {
margin: auto;
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
}
#chart,
#text1,
#text2 {
flex: 1 100%;
text-align: justify;
}
#chart {
flex: 4 0px;
}
#text1 {
order: 1;
}
#chart {
order: 2;
}
#text2 {
order: 3;
}
.node {
cursor: pointer;
}
.node:hover {
stroke: #000;
stroke-width: 1.5px;
}
.node--leaf {
fill: yellow;
}
.label {
font: 11px "Helvetica Neue", Helvetica, Arial, sans-serif;
text-anchor: middle;
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff, 0 -1px 0 #fff;
}
.label,
.node--root,
.node--leaf {
pointer-events: none;
}
</style>
</head>
<body>
<h1> Assists Per Year - La Liga</h1>
<h2> A Zoomable Circle Packing Visualization</h2>
<div id='container'>
<div id='text1'>This visualization employs <a href="https://en.wikipedia.org/wiki/Circle_packing#Unequal_circles">Circle Packing of Circles of Unequal Sizes</a>. Where the sizes of the circles are determined by the size of the contents. In this case, the contents are the number of assists per year by the top players in La Liga.
<br> <br>
For example, from the visualization, we can see that 2015 was the year with the most assists and 2010 was the year with the fewest. The yellow circles signify players and the size of the circles signifies the number of assists that each player had in that year.
</div>
<div id='chart'></div>
<div id='text2'>Click on the inner circles to zoom in</div>
</div>
<script>
// This is a more complicated version.
// The Dataset consists of:
// year,player,appearance,goals,goals_per_game, assists,assists_per_game
// If you click on the year, it will zoom in.
// Basic Options
var margin = 20,
diameter = 960;
var pack = d3.layout.pack().padding(2).size([diameter - margin, diameter - margin]).value(function(d) {
return d.assists;
});
var color = d3.scale.category20c();
var svg = d3.select("#chart").append("svg").attr("width", diameter).attr("height", diameter).append("g").attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");
//*************************************************
// GET THE CSV DATA
//*************************************************
d3.csv("https://s3-us-west-2.amazonaws.com/s.cdpn.io/565729/Football_Data.csv", function(error, data) {
_.each(data, function(element, index, list) {
element.pop = +element.pop;
});
//*************************************************
// THE FUNCTION to turn your data from CSV into
// nested data object (this does the work for you)
//*************************************************
function genJSON(csvData, groups) {
var genGroups = function(data) {
return _.map(data, function(element, index) {
return {
name : index,
children : element
};
});
};
var nest = function(node, curIndex) {
if (curIndex === 0) {
node.children = genGroups(_.groupBy(csvData, groups[0]));
_.each(node.children, function(child) {
nest(child, curIndex + 1);
});
} else {
if (curIndex < groups.length) {
node.children = genGroups(_.groupBy(node.children, groups[curIndex]));
_.each(node.children, function(child) {
nest(child, curIndex + 1);
});
}
}
return node;
};
return nest({}, 0);
}
//*************************************************
// CALL FUNCTION WITH ARRAY OF GROUPS
//*************************************************
// Unlike before, this controls the circles.
// You don't change any other options.
var preppedData = genJSON(data, ['year', 'assists', 'player']);
//*************************************************
// YOUR DATA VISUALIZATION CODE HERE
//*************************************************
var focus = preppedData,
nodes = pack.nodes(preppedData),
view;
console.log(nodes);
var circle = svg.selectAll("circle").data(nodes).enter().append("circle").attr("class", function(d) {
return d.parent ? d.children ? "node" : "node node--leaf" : "node node--preppedData";
}).style("fill", function(d) {
return d.children ? color(d.depth) : null;
}).on("click", function(d) {
if (focus !== d)
zoom(d), d3.event.stopPropagation();
});
var text = svg.selectAll("text").data(nodes).enter().append("text").attr("class", "label").style("fill-opacity", function(d) {
return d.parent === preppedData ? 1 : 0.15;
}).style("display", function(d) {
return d.parent === preppedData ? "inline" : "inline";
}).style("font-size", function(d) {
return d.parent === preppedData ? "24px" : "6px";
}).text(function(d) {
if (typeof d.player != 'undefined'){
var textName = d.player;
}else{
var textName = d.name;
}
return textName;
});
var node = svg.selectAll("circle,text");
d3.select("body").style("background", color(-1)).on("click", function() {
zoom(preppedData);
});
zoomTo([preppedData.x, preppedData.y, preppedData.r * 2 + margin]);
function zoom(d) {
var focus0 = focus;
focus = d;
var transition = d3.transition().duration(d3.event.altKey ? 7500 : 750).tween("zoom", function(d) {
var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2 + margin]);
return function(t) {
zoomTo(i(t));
};
});
transition.selectAll("text").filter(function(d) {
return d.parent === focus || this.style.display === "inline";
}).style("fill-opacity", function(d) {
return d.parent === focus ? 1 : 0.15;
}).style("font-size", function(d) {
return d.parent === focus ? "24px" : "6px";
}).each("start", function(d) {
if (d.parent === focus)
this.style.display = "inline";
}).each("end", function(d) {
if (d.parent !== focus)
this.style.display = "inline";
});
}
function zoomTo(v) {
var k = diameter / v[2];
view = v;
node.attr("transform", function(d) {
return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")";
});
circle.attr("r", function(d) {
return d.r * k;
});
}
});
d3.select(self.frameElement).style("height", diameter + "px");
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment