Skip to content

Instantly share code, notes, and snippets.

@ensley
Last active June 23, 2017 23:07
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save ensley/32def8d94f2b049bd583d8a6763503b7 to your computer and use it in GitHub Desktop.
Interactive NHL Assist Visualization
license: gpl-3.0
height: 800
scrolling: yes
var width = 720,
height = 720,
outerRadius = Math.min(width, height) / 2 - 10,
innerRadius = outerRadius - 24,
textWidth = 300;
var layout = d3.chord()
.padAngle(0.03)
.sortSubgroups(d3.descending)
.sortChords(d3.ascending);
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var ribbon = d3.ribbon()
.radius(innerRadius);
var svg = d3.select('body').append('svg')
.attr('width', width+textWidth)
.attr('height', height)
svg.append('g')
.attr('class', 'label')
.append('text')
.attr('class', 'team')
.attr('x', width+textWidth)
.attr('y', 0)
.text('Pittsburgh Penguins')
svg = svg.append('g')
.attr('id', 'circle')
.attr('transform', 'translate('+width/2+','+height/2+')');
svg.append('circle')
.attr('r', outerRadius);
d3.queue()
.defer(d3.csv, 'roster.csv')
.defer(d3.json, 'matrix.json')
.await(ready);
function ready(error, roster, matrix) {
if (error) throw error;
var chords = layout(matrix);
console.log(chords.groups);
var groups = svg.selectAll('.group')
.data(chords.groups)
.enter().append('g')
.attr('class', 'group')
.on('mouseover', mouseover);
groups.append('title')
.text(function(d, i) {
return roster[i].first + ' ' + roster[i].last + ': ' + d.value + ' assists';
});
var groupPaths = groups.append('path')
.attr('id', function(d, i) { return 'group'+i; })
.attr('class', 'player')
.attr('d', arc)
.style('fill', function(d, i) { console.log(roster[i].color); return roster[i].color; });
var groupText = groups.append('text')
.attr('x', 6)
.attr('dx', 3)
.attr('dy', 15);
groupText.append('textPath')
.attr('xlink:href', function(d, i) { return '#group' + i; })
.text(function(d, i) { return roster[i].last; });
groupText.filter(function(d, i) {
return groupPaths._groups[0][i].getTotalLength() / 2 - 25 < this.getComputedTextLength();
}).remove();
var ribbons = svg.selectAll('.ribbon')
.data(chords)
.enter().append('path')
.attr('class', 'ribbon')
.style('fill', function(d) { return roster[d.source.index].color; })
.attr('d', ribbon);
ribbons.append('title')
.text(function(d) {
return roster[d.source.index].first + ' ' + roster[d.source.index].last
+ ' → ' + roster[d.target.index].first + ' ' + roster[d.target.index].last
+ ': ' + d.source.value + ' assists'
+ '\n' + roster[d.target.index].first + ' ' + roster[d.target.index].last
+ ' → ' + roster[d.source.index].first + ' ' + roster[d.source.index].last
+ ': ' + d.target.value + ' assists'
});
d3.selectAll('.label').append('text')
.attr('class', 'total')
.attr('x', width+textWidth)
.attr('y', '50')
.text('Total assists: '+d3.sum(matrix, function(row) {
return d3.sum(row);
}));
function mouseover(d, i) {
ribbons.classed('fade', function(p) {
return p.source.index != i
&& p.target.index != i;
});
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<style>
#circle circle {
fill: none;
pointer-events: all;
}
svg {
font: 10px sans-serif;
}
.group path {
fill-opacity: .35;
}
path.ribbon {
stroke: #000;
stroke-width: .25px;
fill-opacity: 0.85;
}
#circle:hover path.fade {
display: none;
}
text.team {
font: 48px sans-serif;
text-anchor: end;
dominant-baseline: text-before-edge;
fill: #333;
}
text.total {
font: 36px sans-serif;
text-anchor: end;
dominant-baseline: text-before-edge;
fill: #333;
}
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script type="text/javascript" src="assists.js"></script>
</body>
</html>
[[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,1,0,3,1,2,3,1,2,0,0,4,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0],[0,0,0,1,0,5,0,6,3,0,2,4,0,3,0,12,0,0,0,0,1,0,0,2,0,0,0,5,1,0,0],[0,0,0,0,3,0,0,2,3,0,1,0,0,1,0,1,0,4,0,1,0,1,0,1,0,0,0,0,0,0,0],[1,0,0,3,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,2,7,0,0,0,0,0,2,0,0,2,0,0,0,3,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0],[0,1,2,0,0,0,0,2,4,0,0,4,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0],[0,0,5,2,0,1,2,0,2,0,0,5,0,0,0,2,0,3,1,0,0,0,0,0,0,0,0,0,0,0,0],[0,3,7,1,0,3,1,8,0,0,1,15,0,0,0,1,0,1,1,1,0,1,0,1,0,0,0,2,0,0,0],[1,2,0,3,2,0,0,1,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,3,2,1,1,0,2,0,0,0,6,0,1,0,1,0,0,0,1,0,0,0,0,0,0,1,1,0,0,0],[0,0,6,0,0,2,0,7,7,1,1,0,0,2,0,1,0,0,3,0,0,0,0,0,0,0,2,6,1,0,0],[1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0],[0,2,2,1,0,0,0,0,0,0,1,0,0,0,0,6,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0],[0,0,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,1,16,1,1,3,0,1,1,0,0,1,0,2,0,0,0,0,0,0,0,0,0,0,1,0,0,2,0,0,0],[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[1,3,3,1,1,0,0,0,1,1,2,1,1,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0],[0,4,4,0,0,2,0,1,1,0,3,1,0,2,0,1,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0],[0,2,0,0,0,2,2,0,2,0,0,3,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0],[0,2,3,0,0,2,0,0,2,0,0,2,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,11,1,1,0,0,2,5,1,2,3,0,2,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,1,0,1,2,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,2,1,0,0,2,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,2,7,2,0,2,0,2,5,0,0,7,0,1,0,7,0,0,1,1,0,0,0,2,0,0,0,0,0,0,0],[0,3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0],[0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]
id last first pos posgrp color
5929 Archibald Josh RW F #ffcc33
4775 Bonino Nick C F #ffcc33
3490 Crosby Sidney C F #ffcc33
257 Cullen Matt C F #ffcc33
3819 Fehr Eric RW F #ffcc33
11327 Guentzel Jake C F #ffcc33
5038 Hagelin Carl LW F #ffcc33
4523 Hornqvist Patric RW F #ffcc33
4008 Kessel Phil RW F #ffcc33
5907 Kuhnhackl Tom RW F #ffcc33
898 Kunitz Chris LW F #ffcc33
3652 Malkin Evgeni C F #ffcc33
11710 Rowney Carter RW F #ffcc33
5500 Rust Bryan RW F #ffcc33
4731 Sestito Tom LW F #ffcc33
5892 Sheary Conor LW F #ffcc33
5732 Simon Dominik C F #ffcc33
5492 Wilson Scott C F #ffcc33
4905 Cole Ian D D #040707
701 Daley Trevor D D #040707
5310 Dumoulin Brian D D #040707
4953 Gaunce Cameron D D #040707
203 Hainsey Ron D D #040707
4030 Letang Kris D D #040707
5259 Maatta Olli D D #040707
5181 Oleksy Steve D D #040707
5209 Ruhwedel Chad D D #040707
5118 Schultz Justin D D #040707
3665 Streit Mark D D #040707
5315 Warsofsky David D D #040707
5894 Murray Matthew G G #377EB8
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment