IM LAYING IT ON THICK
ITS A METAPHORRRRR
LOLLLL
json of big cities https://gist.github.com/Miserlou/c5cd8364bf9b2420bb29
@mkearney’s very handy election result data
i don’t trust Oglala Lakota County née Shannon County, fips code 46113
<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {
width: 960px;
margin: 0;
position: relative;
font-size: 14px;
font-family: sans-serif;
text-transform: uppercase;
}
svg {
overflow: visible;
}
.counties {
fill: #ccc;
}
.county-borders {
fill: none;
/*stroke: #ccc;
stroke-width: .5px;*/
stroke-linejoin: round;
stroke-linecap: round;
}
.labels text {
fill: black;
}
button {
position: absolute;
font-size: 14px;
font-family: sans-serif;
text-transform: uppercase;
}
path.trendline {
stroke-width: 2;
stroke: black;
}
</style>
<body>
<script src="//d3js.org/d3.v4.min.js"></script>
<script src="//d3js.org/topojson.v1.min.js"></script>
<script src="//d3js.org/queue.v1.min.js"></script>
<script>
var width = 960,
height = 500;
var projection = d3.geoAlbersUsa()
.translate([width / 2, height / 2]);
var path = d3.geoPath()
.projection(projection);
var colorScale = d3.scaleLinear()
.domain([0,1])
.range(['blue', 'red'])
var color = function(d) {
return d.trumpFraction !== null ? colorScale(d.trumpFraction) : 'none'
}
var color = function(d) {
if(d.trumpFraction === null) return 'none';
return d3.scaleLinear()
.domain([0,1])
.range(['#3c3b6e', '#b22234'])
(d.trumpFraction)
}
var color = function(d) {
return d.trumpFraction !== null ? (d.trumpFraction > .5 ? '#b22234' : '#3c3b6e') : 'none'
}
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
queue()
.defer(d3.json, "us.json")
.defer(d3.tsv, "results.tsv", parseElection)
.defer(d3.json, "cities.json")
.await(ready);
function ready(error, us, election, cities) {
if (error) throw error;
var counties = topojson.feature(us, us.objects.counties);
cities = cities.slice(0,50);
counties.features.forEach(function(county, i) {
// trump!
var countyResults = election.filter(function(d) {
return d.fips === county.id;
});
var hillary = countyResults.filter(function(d) {
return d.cand == "Hillary Clinton"
})[0]
var trump = countyResults.filter(function(d) {
return d.cand == "Donald Trump"
})[0]
if(hillary && trump) {
county.trumpFraction = trump.votes / (hillary.votes + trump.votes);
} else {
county.trumpFraction = null;
}
// centroid
county.centroid = path.centroid(county);
});
var county = svg.append("g")
.attr("class", "counties")
.selectAll("path")
.data(counties.features)
.enter().append("path")
.style("fill", color)
.attr("d", path);
svg.append("path")
.attr("class", "county-borders")
.datum(topojson.mesh(us, us.objects.counties, function(a, b) { return a !== b; }))
.attr("d", path);
// svg.selectAll("circle.city")
// .data(cities)
// .enter()
// .append("circle")
// .classed("city", true)
// .attr("fill", "white")
// .attr("r", 3)
// .attr("cx", function(d) { return projection([d.longitude, d.latitude])[0]; })
// .attr("cy", function(d) { return projection([d.longitude, d.latitude])[1]; })
d3.timer(function(t) {
county.attr("transform", function(d,i) {
var x = (5 * Math.sin(d.centroid[0] * Math.sin(d.centroid[1]) / 50) * Math.sin(t/1000))
var y = (10 * Math.sin(d.centroid[0] / 100 + t/400) + 5 * Math.sin(d.centroid[1] / 10 + t/400))
if(isNaN(x) || isNaN(y)) return;
if(t > 3000) {
var dt = t - 3000;
var dx = d.centroid[0] - .78 * width;
var dy = d.centroid[1] - .41 * height;
x += Math.pow(d.trumpFraction,3) * (.0001 * dx * Math.pow(dx, 2) * (Math.exp(dt/700)-1))
y += Math.pow(d.trumpFraction,3) * (.0001 * dy * Math.pow(dy, 2) * (Math.exp(dt/700)-1))
}
return "translate(" + x + "," + y + ")"
})
})
}
function parseElection (d) {
if((d.cand !== "Donald Trump" && d.cand !== "Hillary Clinton") || isNaN(d.fips)) {
return null;
}
return {
fips: parseInt(d.fips),
cand: d.cand,
votes: parseInt(d.votes)
};
}
// returns slope, intercept and r-square of the line
// from //bl.ocks.org/benvandyke/8459843
function leastSquares(xSeries, ySeries) {
var reduceSumFunc = function(prev, cur) { return prev + cur; };
var xBar = xSeries.reduce(reduceSumFunc) * 1.0 / xSeries.length;
var yBar = ySeries.reduce(reduceSumFunc) * 1.0 / ySeries.length;
var ssXX = xSeries.map(function(d) { return Math.pow(d - xBar, 2); })
.reduce(reduceSumFunc);
var ssYY = ySeries.map(function(d) { return Math.pow(d - yBar, 2); })
.reduce(reduceSumFunc);
var ssXY = xSeries.map(function(d, i) { return (d - xBar) * (ySeries[i] - yBar); })
.reduce(reduceSumFunc);
var slope = ssXY / ssXX;
var intercept = yBar - (xBar * slope);
var rSquare = Math.pow(ssXY, 2) / (ssXX * ssYY);
return {
slope: slope,
intercept: intercept,
rSquare: rSquare
};
}
</script>