block by pstuffa 7e1f39482e9ef585637b626acf2257d9

Threshold Choropleth with Bubbles

Full Screen

index.html

<!DOCTYPE html>
<meta charset="utf-8">

<style>

.states {
  stroke: #000;
  stroke-width: .5;
  fill: none;
}

.bubbles {
  stroke: #000;
  fill-opacity: .5;
}

#popoverText { 
  position: absolute;     
  text-align: center;         
  padding: 2px;       
  font: 12px sans-serif;    
  background: #fff; 
  border: 0px;    
  border-radius: 8px;     
  pointer-events: none;
  opacity: 0;     
}

</style>

<body>
  <div id="buttons">
    <button id="bubblesOn">Turn on Bubbles</button>
    <button id="bubblesOff">Turn off Bubbles</button>
  </div>
  <div id="chart-container">  </div>
  <svg width="700" height="500"></svg>
  <div id='popoverText'> </div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js"></script>
<script>

var margin = {top: 50, right: 5, bottom: 5, left: 30};
var width = 900 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

var svg = d3.select("#chart-container")
    .append("svg")
      .attr("class", "map")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
    .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

queue()
    .defer(d3.csv, "guns-history.csv")
    .defer(d3.json, "us.json")
    .defer(d3.csv, "Poverty Data 2014-Table 1.csv")
    .await(ready);

function ready(error, guns, us, poverty) {

  if (error) throw error;
  console.log(us);
  console.log(poverty)

  var gunsLookup = {};
  guns.forEach(function(d) {
    gunsLookup[d.FIPS] = d.count3;
  })

  var povertyLookup = {};
  poverty.forEach(function(d) {
    d.PCTPOVALL_2014 = +d.PCTPOVALL_2014
    d.FIPStxt = +d.FIPStxt;
    povertyLookup[d.FIPStxt] = d.PCTPOVALL_2014;

  })

  var counties = topojson.feature(us, us.objects.counties),
      states = topojson.feature(us, us.objects.states);

  var path = d3.geoPath()
      .projection(d3.geoAlbersUsa()
        .fitSize([width, height], counties));

  colorScale = d3.scaleThreshold()
      .domain([0, 8, 12, 16, 20, 24, 30, 45])
      .range(["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"]);

  var g = svg.append("g")
      .attr("class", "key")
      .attr("transform", "translate(20,0)");

  var x = d3.scaleLinear()
      .domain(d3.extent(poverty, function(d) { return d.PCTPOVALL_2014 }))
      .range([0, width/2]);

  g.selectAll("rect")
      .data(colorScale.range().map(function(d, i) {
        return {
          y0: i ? x(colorScale.domain()[i - 1]) : x.range()[0],
          y1: i < colorScale.domain().length ? x(colorScale.domain()[i]) : x.range()[1],
          z: d
        };
      }))
    .enter().append("rect")
      .attr("width", 8)
      .attr("y", function(d) { return d.y0; })
      .attr("height", function(d) { return d.y1 - d.y0; })
      .style("fill", function(d) { return d.z; });

  var xAxis = d3.axisLeft(x)
      .tickValues(colorScale.domain())

  g.call(xAxis)

  svg.append("text")
      .attr("class", "caption")
      .attr("x", 0)
      .attr("y", -30)
      .attr("transform", "rotate(90)")
      .style("font", "8px sans-serif")
      .text("2014 Poverty Percent");

  var countyPaths = svg.selectAll(".counties")
      .data(counties.features)
      .enter().append("path")
      .attr("class", "counties")
      .style("fill", function(d) {  
        return colorScale(povertyLookup[d.id]);  
      })
      .attr("d", function(d) { return path(d); })

  var statePaths = svg.selectAll(".states")
        .data(states.features)
        .enter().append("path")
        .attr("class", "states")
        .attr("d", function(d) { return path(d); })
       

  var gunColorScale = d3.scaleThreshold() 
    .domain([1,910,1107,1880,2716,15782])
    .range(["#fff","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a"]);
 
  var gunBubbles = svg.selectAll(".bubbles")
      .data(counties.features)
      .enter().append("circle")
      .attr("class", "bubbles")
      .attr("r", function(d) { return Math.sqrt(gunsLookup[d.id])/Math.PI  })
      .attr("cx", function(d) { return path.centroid(d)[0] })
      .attr("cy", function(d) { return path.centroid(d)[1] })
      .style("fill", function(d) { return gunColorScale(gunsLookup[d.id]); })

d3.selectAll("button")
  .on("click", function() {
    console.log(this.id);

    var bubbleType = this.id;

    d3.selectAll(".bubbles")
        .transition()
        .duration(1200)
        .attr("r", function(d) {
          return (bubbleType == "bubblesOff" ? 0 : Math.sqrt(gunsLookup[d.id])/Math.PI)
        })

  })

}

</script>
</body>