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.
xxxxxxxxxx
<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>
https://d3js.org/d3.v3.min.js