Built with blockbuilder.org
xxxxxxxxxx
<svg width="1100" height="1100"></svg>
<link href='https://fonts.googleapis.com/css?family=Lato:300,400' rel='stylesheet' type='text/css'>
<style>
body {
background: MintCream;
}
svg {
display: block;
margin: auto;
padding: 25px;
}
path {
opacity: 0.85
}
path:hover {
stroke: Yellow;
}
.background {
fill: none;
pointer-events: all;
}
div.tooltip {
background-color: WhiteSmoke;
padding: .5em;
font-family: Lato;
font-size: 12px;
font-weight: bolder;
border-radius: 2px;
opacity: 0.8;
position: absolute;
text-align: left;
margin-top: 20px;
line-height: 1.3em;
}
.legendLinear {
font-family: Lato;
font-size: 14px;
font-weight: lighter;
}
.hidden {
display: none;
}
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.24.0/d3-legend.min.js"></script>
<script>
var svg = d3.select("svg"),
width = 1100,
height = 1100,
active = d3.select(null);
var zoom = d3.zoom()
.scaleExtent([1, 8])
.on("zoom", zoomed);
var color = d3.scaleThreshold()
.domain([-35,-23,-14,-7,-2,0,2,7,14,23,35])
.range(d3.schemeRdBu[11]);
var x = d3.scaleLinear()
.domain([-35,35])
.rangeRound([-20, 20]);
var tooltip = d3.select('body').append('div')
.attr('class', 'hidden tooltip');
var linear = d3.scaleOrdinal()
.domain(['35% more Rep. votes than Dem. votes','23% more Rep. votes than Dem. votes','15% more Rep. votes than Dem. votes','7% more Rep. votes than Dem. votes','2% more Rep. votes than Dem. votes','Even Rep. votes and Dem. votes (+/-2%)','2% more Dem. votes than Rep. votes','7% more Dem. votes than Rep. votes','15% more Dem. votes than Rep. votes','23% more Dem. votes than Rep. votes','35% more Dem. votes than Rep. votes'])
.range(d3.schemeRdBu[11]);
svg.append("svg")
.attr("width", width)
.attr("height", height)
.on("click", stopped, true);
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", reset);
var legendLinear = d3.legendColor()
.shapeWidth(15)
.cells(11)
.orient('vertical')
.scale(linear);
svg.append("g")
.attr("class", "legendLinear")
.attr("transform", "translate(20,20)")
.attr('stroke','black');
var path = d3.geoPath();
var g = svg.append("g");
svg
.call(zoom);
d3.json("pctresults-simple-topo.json", function(error, topology) {
if (error) throw error;
g.append("g")
.selectAll("path")
.data(topojson.feature(topology, topology.objects.tracts).features)
.enter().append("path")
.attr("fill", function(d) { return color(d.properties.diff_c); })
.attr("d", path)
.on("click", clicked)
.on('mousemove', function(d) {
var mouse = d3.mouse(svg.node()).map(function(d) {
return parseInt(d);
});
tooltip.classed('hidden', false)
.attr('style', 'left:' + (d3.event.pageX +12) +
'px; top:' + (d3.event.pageY - 2) + 'px')
.html("Precinct: " + d.properties.precinct +'<br>' +"Registered: " + d.properties.registered +'<br>' + "Ballots Cast: " + d.properties.ballotsCast +'<br>' + "Clinton: " + d.properties.Clinton + "%" + '<br>' + "Trump: " +d.properties.Trump + "%" + '<br>' + "Johnson: " + d.properties.Johnson + "%" + '<br>' + "None: " + d.properties.None + "%");
})
.on('mouseout', function() {
tooltip.classed('hidden', true)
});;
g.append("path")
.datum(topojson.feature(topology, topology.objects.tracts))
.attr("fill", "none")
.attr("stroke", "WhiteSmoke")
.attr("stroke-opacity", 0.4)
.attr("d", path);
svg.select(".legendLinear")
.call(legendLinear)
.attr("transform", "translate(0,0)");
});
function clicked(d) {
if (active.node() === this) return reset();
active.classed("active", false);
active = d3.select(this).classed("active", true);
var bounds = path.bounds(d),
dx = bounds[1][0] - bounds[0][0],
dy = bounds[1][1] - bounds[0][1],
x = (bounds[0][0] + bounds[1][0]) / 2,
y = (bounds[0][1] + bounds[1][1]) / 2,
scale = Math.max(1, Math.min(8, 0.9 / Math.max(dx / width, dy / height))),
translate = [width / 2 - scale * x, height / 2 - scale * y];
svg.transition()
.duration(750)
.call( zoom.transform, d3.zoomIdentity.translate(translate[0],translate[1]).scale(scale) ); // updated for d3 v4
}
function reset() {
active.classed("active", false);
active = d3.select(null);
svg.transition()
.duration(750)
.call( zoom.transform, d3.zoomIdentity ); // updated for d3 v4
}
function zoomed() {
g.style("stroke-width", 1.5 / d3.event.transform.k + "px");
g.attr("transform", d3.event.transform); // updated for d3 v4
}
// If the drag behavior prevents the default click,
// also stop propagation so we don’t click-to-zoom.
function stopped() {
if (d3.event.defaultPrevented) d3.event.stopPropagation();
}
</script>
https://d3js.org/d3.v4.min.js
https://d3js.org/d3-scale-chromatic.v1.min.js
https://d3js.org/topojson.v2.min.js
https://cdnjs.cloudflare.com/ajax/libs/d3-legend/2.24.0/d3-legend.min.js