xxxxxxxxxx
<meta charset="utf-8">
<link href='https://fonts.googleapis.com/css?family=Cardo:400,400italic,700' rel='stylesheet' type='text/css'>
<link href="https://fonts.googleapis.com/css?family=Bungee+Hairline" rel="stylesheet">
<style>
h2 {
font-family: 'Cardo';
font-size: 18px;
font-style: italic;
font-weight: 400;
/* font-family: 'Bungee Hairline', cursive;
font-size: 18px;
text-anchor: middle*/
}
h3{
font-family: "BaskOldFace, Baskerville Old Face";
font-size: 13px;
fill: #000000;
font-weight: normal;
}
body {
background: radial-gradient(720px at 490px, #081f2b 0%, #061616 100%);
height: 960px;
}
.counties {
stroke: #bfbfbf;
stroke-width: .25;
fill: #fff;
}
.states {
stroke: #000;
stroke-width: .25;
fill: none;
}
.bubbles {
stroke: #bfbfbf;
fill-opacity: .7;
stroke-linecap: round;
}
button {
font-family: Futura;
}
.q0-9 { fill:rgb(247,251,255); }
.q1-9 { fill:rgb(222,235,247); }
.q2-9 { fill:rgb(198,219,239); }
.q3-9 { fill:rgb(158,202,225); }
.q4-9 { fill:rgb(107,174,214); }
.q5-9 { fill:rgb(66,146,198); }
.q6-9 { fill:rgb(33,113,181); }
.q7-9 { fill:rgb(8,81,156); }
.q8-9 { fill:rgb(8,48,107); }
#popoverText {
position: absolute;
text-align: center;
padding: 2px;
font-family: Futura;
background: #fff;
border: 0px;
border-radius: 8px;
pointer-events: none;
opacity: 0;
}
</style>
<body>
<div class="g-chart-container">
<h2 style="color:white"> 2016 Presidential Election: Percentage Democratic and Polling Places by County</h2>
<!-- <h3 style="color:white"> a map by sami rubenfeld </h3> -->
</div>
<button id="bubblesOn">Turn on Bubbles</button>
<button id="bubblesOff">Turn off Bubbles</button>
<svg width="960" height="720"></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="./d3-lasso.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js"></script>
<script>
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var rateById = d3.map();
var quantize = d3.scaleQuantize()
.domain([0, 1])
.range(d3.range(9).map(function(i) { return "q" + i + "-9"; }));
d3.queue()
.defer(d3.csv, "poll_data_2016.csv")
.defer(d3.csv, "final_edit.csv", function(d) { rateById.set(d.combined_fips, +d.per_dem); })
// .defer(d3.csv, "poll_data_2012.csv")
.defer(d3.json, "us.json")
.await(ready);
function ready(error, polls, final, us) {
if (error) throw error;
console.log(topojson.feature(us, us.objects.counties).features);
pollsLookup = {};
polls.forEach(function(d) {
d.poll_places = +d.poll_places;
d.year = +d.year;
pollsLookup[d.combined_fips] = d.poll_places;
})
locationLookup = {};
polls.forEach(function(d) {
locationLookup[d.combined_fips] = d.county;
})
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));
var defs = svg.append("defs");
//Create a radial Sun-like gradient
defs.append("radialGradient")
.attr("id", "sun-gradient")
.attr("cx", "50%") //not really needed, since 50% is the default
.attr("cy", "50%") //not really needed, since 50% is the default
.attr("r", "50%") //not really needed, since 50% is the default
.selectAll("stop")
.data([
{offset: "0%", color: "rgb(255,255,217)"},
{offset: "50%", color: "rgb(237,248,177)"},
{offset: "90%", color: "rgb(199,233,180)"},
{offset: "100%", color: "rgb(127,205,187)"}
])
.enter().append("stop")
.attr("offset", function(d) { return d.offset; })
.attr("stop-color", function(d) { return d.color; });
//Filter for the outside glow
var filter = defs.append("filter")
.attr("id","glow");
filter.append("feGaussianBlur")
.attr("stdDeviation","3.5")
.attr("result","coloredBlur");
var feMerge = filter.append("feMerge");
feMerge.append("feMergeNode")
.attr("in","coloredBlur");
feMerge.append("feMergeNode")
.attr("in","SourceGraphic");
svg.append("g")
.attr("class", "counties")
.selectAll("path")
.data(topojson.feature(us, us.objects.counties).features)
.enter().append("path")
.attr("stroke", "#bfbfbf")
.attr("stroke-width", .2)
.attr("stroke-opacity", 0.5)
.attr("class", function(d) { return quantize(rateById.get(d.id)); })
.attr("d", path)
.on("mouseenter", function(d) {
console.log(d);
d3.select(this)
.style("stroke-width", .5)
d3.select("#neighborhoodPopover")
.transition()
.style("opacity", 1)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY) + "px")
.text(rateById.get(d.id))
})
.on("mouseleave", function(d) {
d3.select(this)
.style("stroke-width", .25)
.style("stroke-dasharray", 1)
d3.select("#neighborhoodPopovercountyText")
.transition()
.ease(d3.easeElastic)
.style("opacity", 0);
});
var pollsColorScale = d3.scaleThreshold()
// .domain([1,910,1107,1880,2716,15782])
.range(["rgb(247,251,255)","rgb(222,235,247)","rgb(198,219,239)","rgb(158,202,225)","rgb(107,174,214)","rgb(66,146,198)", "rgb(8,48,107)"]);
var pollsBubbles = svg.selectAll(".bubbles")
.data(counties.features)
.enter().append("circle")
.attr("class", "bubbles")
.attr("r", function(d) { return Math.sqrt(pollsLookup[d.id])/Math.PI })
.attr("cx", function(d) { return path.centroid(d)[0] })
.attr("cy", function(d) { return path.centroid(d)[1] })
.style("fill", "url(#sun-gradient)");
d3.selectAll("button")
.on("click", function() {
console.log(this.id);
var bubbleType = this.id;
d3.selectAll(".bubbles")
.transition()
.ease(d3.easeElastic)
.duration(3000)
.attr("r", function(d) {
return (bubbleType == "bubblesOff" ? 0 : Math.sqrt(pollsLookup[d.id])/Math.PI)
})
d3.selectAll(".bubbles")
.style("fill", "url(#sun-gradient)")
.style("filter","url(#glow)");
svg.append("path")
.datum(topojson.mesh(us, us.objects.states.id, function(a, b) { return a !== b; }))
.attr("class", "states")
.attr("d", path);
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "states")
.attr("d", path);
svg.append("g")
.attr("id", "states")
.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("d", path)
.on("click", clicked);
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("id", "state-borders")
.attr("d", path);
})
var statePaths = svg.selectAll(".states")
.data(states.features)
.enter().append("path")
.attr("class", "states")
.attr("d", function(d) { return path(d); })
d3.selectAll(".states")
.style("filter", "url(#glow)");
}
</script>
</body>
https://d3js.org/d3.v4.min.js
https://d3js.org/topojson.v1.min.js
https://cdnjs.cloudflare.com/ajax/libs/queue-async/1.0.7/queue.min.js