block by tophtucker 631d0ba2ddf1ef1bb18a8e0fffd43867

Floppy map

Full Screen

IM LAYING IT ON THICK

ITS A METAPHORRRRR

LOLLLL


index.html

<!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>