function make_boundaries(boundaries) {
let svg = d3.create("svg").attr("width", w).attr("height", h);
let map = svg.append("g");
map
.append("g")
.selectAll("path.boundary")
.data(boundaries.features)
.join("path")
.attr("class", "boundary")
.attr("data-district_votes", function (o) {
return `${o.properties.district}-${o.properties.dem_vote}-${o.properties.rep_vote}`;
})
.attr("fill", "white")
.attr("fill-opacity", 0)
.attr("stroke", "#333")
.attr("stroke-width", 2)
.attr("stroke-linejoin", "round")
.attr("d", path)
.on("pointerenter", function () {
d3.selectAll("path.boundary").attr("fill-opacity", 0.4);
d3.select(this).attr("fill-opacity", 0).attr("stroke-width", 5).raise();
})
.on("pointerleave", function () {
d3.selectAll("path.boundary")
.attr("fill-opacity", 0)
.attr("stroke-width", 2);
});
map
.append("g")
.selectAll("circle.city")
.data(cities)
.join("circle")
.attr("class", "city")
.attr("cx", (o) => o.x)
.attr("cy", (o) => o.y)
.attr("r", 4)
.attr("fill", "black")
.attr("stroke", "white")
.attr("stroke-width", 2)
.attr("pointer-events", "none");
let city_background_container = map
.append("g")
.attr("id", "city_background_container");
let city_name_display = map.append("g");
city_name_display
.selectAll("text.city")
.data(cities)
.join("text")
.attr("class", "city")
.attr("x", (o) => o.x)
.attr("y", (o) => o.y)
.attr("dx", (o) => (o.city == "Winston-Salem" ? (-90 * width) / 1100 : 3))
.attr("dy", (o) => (o.city == "Winston-Salem" ? (-15 * width) / 1100 : -3))
.attr("opacity", show_cities ? 1 : 0)
.text((o) => o.city)
.style("font-family", "sans-serif")
.attr("font-size", (14 * width) / 1100)
.attr("pointer-events", "none");
map
.selectAll("path.boundary")
.nodes()
.forEach(function (d, i) {
let [district, dem, rep] = d
.getAttribute("data-district_votes")
.split("-")
.map((x) => parseInt(x));
let total = dem + rep;
let dprop = dem / total;
let rprop = rep / total;
let dpct = d3.format("0.1%")(dem / total);
let rpct = d3.format("0.1%")(rep / total);
let lean;
if (dprop < rprop) {
lean = `R +${d3.format("0.1%")(rprop - state_dem_proportion)}`;
} else {
lean = `D +${d3.format("0.1%")(dprop - state_dem_proportion)}`;
}
let content = `
<div>
<div>
<div style="display: inline-block; margin-right: 5px">
District: ${district}
</div>
<div style="display: inline-block">
Lean: ${lean}
</div>
</div>
</div>`;
tippy(d, {
content: content,
allowHTML: true,
theme: "light-border",
followCursor: true
});
});
return svg.node();
}