Skip to content

Instantly share code, notes, and snippets.

@jcnesci
Last active September 16, 2016 06:40
Show Gist options
  • Save jcnesci/abdda0bcf5206b3be3e6853e677eb0a8 to your computer and use it in GitHub Desktop.
Save jcnesci/abdda0bcf5206b3be3e6853e677eb0a8 to your computer and use it in GitHub Desktop.
Upcoming shouting match at d3.unconf
license: gpl-3.0
height: 600

My submission for a d3.unconf 2016 ticket... Data from somewhere? Something about Trump and Hillary shouting at each other. Shoulda/coulda/woulda put noises of them doing that. Oh well.

State Clinton Trump Unsure Margin of Error Electoral College Votes
AK 31.5% 52.5% 16% 4.3% 3
AL 33.3% 52.3% 14.4% 2.3% 9
AR 36.6% 46.7% 16.7% 2.6% 6
AZ 37.9% 45.8% 16.3% 2.1% 11
CA 52.1% 32.3% 15.7% 1.3% 55
CO 45.3% 37% 17.7% 2.2% 9
CT 44.6% 39.6% 15.8% 3% 7
DC 65.7% 20.2% 14.1% 2.7% 3
DE 44.5% 39.4% 16.1% 2.9% 3
FL 42.6% 42.1% 15.4% 1.4% 29
GA 42.8% 41.8% 15.5% 1.7% 16
HI 49.6% 30.5% 19.9% 3.1% 4
IA 40.1% 40.1% 19.9% 2.3% 6
ID 33.8% 44.8% 21.4% 2.9% 4
IL 48.2% 35.2% 16.7% 1.8% 20
IN 36.7% 45% 18.3% 2.1% 11
KS 35% 45.6% 19.4% 2.5% 6
KY 34.7% 49.1% 16.3% 2.1% 8
LA 32.9% 50.7% 16.4% 2.5% 8
MA 49.8% 33.3% 16.9% 2.2% 11
MD 51.1% 32.8% 16.1% 2.5% 10
ME 38.8% 40.8% 20.4% 3.4% 4
MI 41.9% 39.3% 18.8% 2.1% 16
MN 45% 35.2% 19.8% 2.6% 10
MO 36.6% 45.2% 18.2% 2.3% 10
MS 33.2% 51.1% 15.8% 2.5% 6
MT 35.8% 45.3% 18.9% 2.6% 3
NC 40.2% 43.2% 16.6% 1.8% 15
ND 35.6% 44.2% 20.2% 2.5% 3
NE 35.3% 47.7% 17% 2.7% 5
NH 41.3% 40.5% 18.2% 3% 4
NJ 46.3% 36.6% 17.1% 2% 14
NM 42.7% 39.8% 17.4% 3.2% 5
NV 43.5% 39.6% 16.9% 2.7% 6
NY 50.9% 33.7% 15.4% 1.3% 29
OH 40.9% 41.7% 17.4% 1.6% 18
OK 33.9% 47.9% 18.2% 3% 7
OR 45.1% 36.3% 18.7% 2.2% 7
PA 42.5% 42.1% 15.3% 1.5% 20
RI 47.3% 35.7% 17% 3% 4
SC 36.6% 46.2% 17.1% 2.4% 9
SD 32.4% 46.7% 20.9% 3.4% 3
TN 33.4% 49% 17.6% 1.9% 11
TX 38.2% 43.5% 18.3% 1.3% 38
UT 33.3% 44.8% 21.9% 3.5% 6
VA 43.6% 38.9% 17.5% 1.9% 13
VT 48.5% 32.1% 19.4% 3.8% 3
WA 47.6% 33.8% 18.5% 2.1% 12
WI 41.4% 39.4% 19.1% 2.3% 10
WV 27.9% 55.7% 16.4% 2.6% 5
WY 24.5% 58.5% 16.9% 3.4% 3
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.bubble {
stroke-width: 10px;
}
.bar {
fill: silver;
}
.bar:hover {
fill: rgb(90,90,90);
}
.axis {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path {
display: none;
}
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var margin = {top: 20, right: 20, bottom: 30, left: 40},
width = 960 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom,
heightBubble = height * 0.6,
heightBarchart = height * 0.4;
var svgParent = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
var svgBubble = svgParent.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var svgBarchart = svgParent.append("g")
.attr("transform", "translate(" + margin.left + "," + (margin.top + heightBubble) + ")");
var fontSize = 92;
//
svgBubble.append("text")
.attr("id", "votes-clinton")
.attr("x", 0)
.attr("y", heightBubble/2)
.style("fill", "blue")
.style("font-size", fontSize +"px")
.style("font-weight", "bold")
.style("font-family", "sans-serif")
.text("Clinton");
svgBubble.append("text")
.attr("id", "votes-trump")
.attr("x", width)
.attr("y", heightBubble/2)
.style("fill", "red")
.style("font-size", fontSize +"px")
.style("font-weight", "bold")
.style("font-family", "sans-serif")
.style("text-anchor", "end")
.text("Trump");
var nodes = [
{
candidate: 'clinton',
radius: 40,
img1: 'clinton-1.jpg',
img2: 'clinton-2.jpg',
color: "blue"
},
{
candidate: 'trump',
radius: 40,
img1: 'trump-1.jpg',
img2: 'trump-2.jpg',
color: "red"
}];
var defs = svgBubble.append("svg:defs");
var images = [];
nodes.forEach(function(d){
images.push( {candidate: d.candidate, img: d.img1, type: 'not-yelling'} );
images.push( {candidate: d.candidate, img: d.img2, type: 'yelling'} );
});
defs.selectAll("pattern")
.data(images)
.enter().append("pattern")
.attr("id", function(d){ return "img-"+ d.candidate +"-"+ d.type; })
.attr("width", 1)
.attr("height", 1)
.attr("viewBox", "0 0 100 100")
.attr("preserveAspectRatio", "none")
.append("image")
.attr("width", 100)
.attr("height", 100)
.attr("xlink:href", function(d){ return d.img; })
.attr("preserveAspectRatio", "none");
var force = d3.layout.force()
.gravity(5)
.charge(10)
.linkDistance(-2000)
.nodes(nodes)
.size([width, heightBubble])
.start();
var bubbles = svgBubble.selectAll("circle")
.data(nodes)
.enter().append("circle")
.attr("id", function(d){ return d.candidate; })
.attr("class", "bubble")
.attr("r", function(d) { return d.radius; })
.style("stroke", function(d){ return d.color; })
.style("fill", function(d){ return "url(#img-"+ d.candidate +"-not-yelling)"; });
force.on("tick", function(e) {
var q = d3.geom.quadtree(nodes),
i = 0,
n = nodes.length;
while (++i < n) q.visit(collide(nodes[i]));
svgBubble.selectAll("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
function collide(node) {
var r = node.radius + 16,
nx1 = node.x - r,
nx2 = node.x + r,
ny1 = node.y - r,
ny2 = node.y + r;
return function(quad, x1, y1, x2, y2) {
if (quad.point && (quad.point !== node)) {
var x = node.x - quad.point.x,
y = node.y - quad.point.y,
l = Math.sqrt(x * x + y * y),
r = node.radius + quad.point.radius;
if (l < r) {
l = (l - r) / l * .5;
node.x -= x *= l;
node.y -= y *= l;
quad.point.x += x;
quad.point.y += y;
}
}
return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
};
}
//
d3.tsv('elections.tsv', function(error, data) {
if (error) throw error;
data.forEach(function(d){
d['Electoral College Votes'] = +d['Electoral College Votes'];
d.Clinton = +(d.Clinton.replace('%',''));
d.Trump = +(d.Trump.replace('%',''));
d.Unsure = +(d.Unsure.replace('%',''));
d['Margin of Error'] = +(d['Margin of Error'].replace('%',''));
});
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .1);
var y = d3.scale.linear()
.range([heightBarchart, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickValues(function(){ return y.domain(); });
x.domain(data.map(function(d) { return d.State; }));
y.domain([0, d3.max(data, function(d) { return d['Electoral College Votes']; })]);
svgBarchart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + heightBarchart + ")")
.call(xAxis);
svgBarchart.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Electoral College Votes");
d3.selectAll('.y.axis path').remove();
svgBarchart.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) { return x(d.State); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(d['Electoral College Votes']); })
.attr("height", function(d) { return heightBarchart - y(d['Electoral College Votes']); })
.on('mouseover', function(d){
nodes[0].radius = d.Clinton;
nodes[0].radius += (nodes[0].radius * nodes[0].radius)/30;
nodes[1].radius = d.Trump;
nodes[1].radius += (nodes[1].radius * nodes[1].radius)/30;
//
var bubbleInFront, bubbleInBack;
if (d.Clinton >= d.Trump) {
bubbleInFront = "trump";
bubbleInBack = "clinton";
} else {
bubbleInFront = "clinton";
bubbleInBack = "trump";
}
d3.select( ".bubble#"+bubbleInFront ).moveToFront();
d3.select( ".bubble#"+bubbleInFront ).style("fill", function(d){ return "url(#img-"+ d.candidate +"-not-yelling)"; });
d3.select( ".bubble#"+bubbleInBack ).style("fill", function(d){ return "url(#img-"+ d.candidate +"-yelling)"; });
//
bubbles
.transition()
.duration(100)
// .attr("r", function(d) { return d.radius + (d.radius * d.radius)/30; })
.attr("r", function(d) { return d.radius; })
.attr("cx", function(d) {
return d.x + ((Math.random() - .5) * 50);
})
.attr("cy", function(d) {
return d.y + ((Math.random() - .5) * 50);
});
//
d3.select("#votes-clinton").text(d.Clinton +"%");
d3.select("#votes-trump").text(d.Trump +"%");
d3.select("#votes-"+bubbleInFront).style("font-size", fontSize/2 +"px");
d3.select("#votes-"+bubbleInBack).style("font-size", fontSize +"px");
});
});
d3.selection.prototype.moveToFront = function() {
return this.each(function(){
this.parentNode.appendChild(this);
});
};
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment