Built with blockbuilder.org
forked from sxywu‘s block: d3unconf 2016, v1
forked from sxywu‘s block: d3unconf 2016, v2
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
<script src="https://npmcdn.com/babel-core@5.8.34/browser.min.js"></script>
<script type="text/javascript" src="//gka.github.io/chroma.js/vendor/chroma-js/chroma.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0;
}
svg {
width: 100%;
height: 100%;
}
text {
font-family: courier;
}
/* blend options taken from visual cinnamon tutorial: //www.visualcinnamon.com/2016/05/beautiful-color-blending-svg-d3.html */
/*Set isolate on the group element*/
svg {isolation: isolate;}
/*Set blend mode on SVG element: e.g. screen, multiply*/
/* path { mix-blend-mode: multiply; } */
</style>
</head>
<body>
<svg></svg>
<script type="text/babel">
var width = 800;
var height = 800;
var yellow = chroma('#FFFEDE').saturate(3);
var navy = '#000e20';
var blue = chroma(navy).brighten(.5).saturate();
var white = chroma(navy).brighten(4);
var colors = chroma.scale([blue, navy])
.mode('hsl')
.colors(6);
d3.csv('data.csv', (data) => {
var attendees = _.map(data, d => {
return {
name: d['First Name'],
first: d.first.split(', '),
favorite: d.favorite.split(', '),
version: parseInt(d.version.replace('v', '')),
};
});
// create links between the different types
// of firsts, favorites, and versions
var firsts = _.chain(attendees)
.map('first').flatten()
.countBy().toPairs()
.sortBy(d => -d[1])
.filter(d => d[0] !== 'N/A')
.map(0).value();
var favorites = _.chain(attendees)
.map('favorite').flatten()
.countBy().toPairs()
.sortBy(d => -d[1])
.filter(d => d[0])
.map(0).value();
var versions = _.chain(attendees)
.map('version').flatten()
.countBy().toPairs()
// .sortBy(d => -d[1])
.filter(d => d[1] > 1)
.map(0).value();
/**************************************
** calculate nodes and links
**************************************/
// radius should be attendee's first experience with dataviz
var startRad = width * .01;
var perRad = width / firsts.length * .3;
var radiusScale = d3.scaleOrdinal().domain(firsts)
.range(_.times(firsts.length, (i) => (i + 1) * perRad + startRad));
var startAngle = -.5 * Math.PI;
// angle is their current fav d3 API
var perAngle = (2 * Math.PI) / favorites.length;
var angleScale = d3.scaleOrdinal().domain(favorites)
.range(_.times(favorites.length, (i) => i * perAngle + startAngle));
// YAH LOOPS
var points = [];
_.each(attendees, attendee => {
_.each(attendee.favorite, favorite => {
var angle = angleScale(favorite);
_.each(attendee.first, first => {
var radius = radiusScale(first);
points.push({
name: attendee.name,
favorite,
first,
version: attendee.version,
focusX: Math.cos(angle) * radius,
focusY: Math.sin(angle) * radius,
});
});
});
});
// also loop through the favorites to
// make an actual circle
var outside = [];
var favoriteRad = width * .45;
_.each(favorites, favorite => {
var angle = angleScale(favorite);
outside.push({
fx: Math.cos(angle) * favoriteRad,
fy: Math.sin(angle) * favoriteRad,
});
});
var nodes = _.union(points, outside);
var simulation = d3.forceSimulation(nodes)
.force('charge', d3.forceManyBody())
.force("collide", d3.forceCollide(2))
.force("x", d3.forceX().x(d => d.focusX))
.force("y", d3.forceY().y(d => d.focusY))
.on("tick", ticked);
var voronoi = d3.voronoi()
.x(d => d.x)
.y(d => d.y);
/**************************************
** draw the circles and links
**************************************/
var svg = d3.select('svg')
.append('g')
.attr('transform', 'translate(' + [width / 2, height / 2] + ')');
// motion blur taken from //www.visualcinnamon.com/2016/05/real-life-motion-effects-d3-visualization.html
var defs = svg.append("defs");
defs.append("filter")
.attr("id", "motionFilter")
.attr('width', '300%')
.attr('height', '300%')
.attr('x', '-100%')
.attr('y', '-100%')
.append("feGaussianBlur")
.attr("in", "SourceGraphic")
.attr("stdDeviation", "2");
var pathContainer = svg.append('g');
var paths, triangles;
var circles = svg.selectAll('g')
.data(points)
.enter().append('g');
// first the blur
circles.append('circle')
.attr('fill', yellow)
.attr('r', d => (4 / d.version - 1) * 3.5)
.attr('opacity', .25)
.style("filter", "url(#motionFilter)");
// then the actual star
circles.append('circle')
.attr('fill', yellow)
.attr('r', d => (4 / d.version - 1) * .75);
// add in text
var fontSize = 89;
var text = svg.append('g')
.attr('opacity', .75);
text.append('text')
.attr('text-anchor', 'middle')
.attr('dy', '.35em')
.attr('y', -fontSize * 1.15)
.attr('fill', white)
.attr('font-size', fontSize * .85)
.text('d3.unconf');
text.append('text')
.attr('text-anchor', 'middle')
.attr('dy', '.35em')
.attr('y', fontSize * .3)
.attr('fill', white)
.attr('font-size', fontSize * 2.5)
.text('2016');
text.append('line')
.attr('x1', -fontSize * 2)
.attr('x2', fontSize * 2)
.attr('y1', fontSize * 1.75)
.attr('y2', fontSize * 1.75)
.attr('stroke', white)
.attr('stroke-width', fontSize / 9)
.attr('stroke-linecap', 'round')
text.append('line')
.attr('x1', -fontSize * 2)
.attr('x2', fontSize * 2)
.attr('y1', -fontSize * 1.75)
.attr('y2', -fontSize * 1.75)
.attr('stroke', white)
.attr('stroke-width', fontSize / 9)
.attr('stroke-linecap', 'round')
function ticked() {
circles.attr('transform', (d) =>
'translate(' + [d.x, d.y] + ')');
triangles = voronoi.triangles(nodes);
// now create the triangles
paths = pathContainer.selectAll('path')
.data(triangles);
paths.exit().remove();
paths.enter().append('path')
.merge(paths)
.attr('d', d => {
return 'M' + _.map(d, function(point) {
return point.x + ',' + point.y;
}).join(' L') + 'Z';
}).attr('fill', (d, i) => colors[i % 6])
.attr('stroke', (d, i) => colors[i % 6])
.attr('opacity', .85);
}
});
</script>
</body>
First Name,version,first,favorite
Alan,v1,Scatter plot,d3.timer
Alanna,v3,"Bar chart, Line chart",
Alastair,v1,Treemap,d3.forceSimulation
Alex,v3,Line chart,d3.transition
Amit,v1,N/A,d3.behavior.zoom
Andrew,v3,Radial plot,d3.scale
Angela,v2,Scatter plot,
Anna,v3,Bar chart,
Anna,v2,Tree,d3.line
Anuja,v3,Tree,d3.hierarchy
Bo,v3,Line chart,selection.data
Brad,v2,Chord diagram,d3.selectAll
Brent,v3,Bar plot,d3.forceSimulation
Brian,v4,Bar chart,d3.voronoi
Casey,v3,Bar chart,d3.force
Chris,v3,Time series,d3.transition
Christophe,v1,Tooltip,d3.axis
Daniel,v3,Scatter plot,d3.nest
Daniel,v3,Map,d3.transition
David,v3,Force,d3.interpolate
David,v3,Charting library,d3.voronoi
David,v3,Bar chart,selection.data
Don,v3,Choropleth,d3.voronoi
Eric,v3,Map,d3.transition
Erik,v3,Scatter plot,selection.data
Erik,v1,Radar chart,d3.voronoi
Francois,v3,Bar chart,d3.scale
Marcos,v3,Bar chart,d3.selectAll
Hourann,v3,"Map, Bubble chart",d3.scaleOrdinal
Ian,v1,Bar chart,d3.scaleLinear
Ivy,v1,Network graph,nest.rollup
James,v3,Scatter plot,d3.scale
James,v3,Line chart,nest.map
Jamie,v2,Map,transform
Janine,v3,Bar chart,d3.selection
Jay,v3,Bar chart,d3.scale
Jeff,v2,Map,d3.geoProjection
Jeffrey,v2,Line chart,d3.voronoi
Jennifer,v3,Bar chart,d3.transition
Jeremy,v3,Line Chart,d3.geoProjection
Jeremy,v2,Bar chart,d3.scale
Jim,v2,Bubble chart,d3.nest
Jing,v4,Scatter plot,d3.brush
John,v2,Area chart,d3.histogram
John,v3,Scatter plot,d3.transition
Jon,v4,Bar chart,d3.transition
Jon,v2,Bar chart,d3.extent
Jonathan,v2,Bar chart,scale.invert
Kai,v1,Chord diagram,d3.interpolateMagma
Ken,v3,Bar chart,d3.forceSimulation
Kerry,v1,Chord diagram,d3.scale
Krist,v3,Scatter plot,"d3.selection, d3.scale"
Kristen,v3,Pie chart,d3.transition
Kristin,v2,Chloropleth,d3.scale
Leland,v3,Bar chart,arcTween
Logan,v4,"Pie chart, Donut chart",d3.pie
Ludwig,v3,Tree,projection.fitSize
Marie,v3,Line chart,d3.transition
Mark,v2,Tree,d3.line
Matthew,v4,Scatter plot,d3.scale
Mauro,v3,Sunburst,selection.data
Micah,v3,Map,d3.request
Michael,v2,Bar chart,d3.pack
Mike,v1,N/A,d3.pack
Minwei,v4,bar chart,d3.layout.force
Naoya,v3,bar chart,d3.scale
Noah,v2,Line chart,d3.transition
Patrick,v3,Scatter Plot,selection.attr
Paul,v4,Scatter plot,d3.selectAll
Paul,v1,Bar chart,d3.scale
Philippe,v3,Map,d3.geoProjection
Phillip,v4,Donut chart,"d3.scale, d3.zoom"
Ramesh,v4,Scatter plot,d3.scale
Ric,v3,Line chart,d3.brush
Robert,v3,Bar chart,d3.nest
Robert,v2,Force,d3.scale
Roger,v3,Map,d3.geo
Rumman,v3,Line chart,d3.voronoi
Saniya,v3,Scatter plot,d3.color
Sara,v2,Circle pack,d3.nest
Sara,v3,Scatter plot,
Sarah,v4,Donut chart,d3.transition
Seemant,v3,Donut chart,d3.nest
Shan,v2,Bubble chart,d3.scaleLinear
Shelby,v3,Scatter plot,d3.scale
Shirley,v2,Tree,d3.forceSimulation
Siu-Mei,v4,Bar chart,d3.voronoi
Susie,v2,Bar chart,d3.nest
Tarek,v2,Bar chart,d3.layout.pack
Tim Hyon,v3,Parallel coordinates,d3.scale
Tony,v3,Bubble chart,d3.scale
Toshiyuki,v3,Network graph,"selection.enter, selection.exit"
Vasco,v2,Force,selection.data
Victor,v4,Scatter plot,d3.geo.path
Visnu,v2,Bar chart,d3.nest
Xianlin,v3,Force,d3.transition
Yukiko,v3,Bar chart,d3.color
Zack,v2,Bar chart,selection.enter