Public
Edited
May 25, 2023
Insert cell
Insert cell
height = 600
Insert cell
spreadConstituencies = applySimulation(constituencies);
Insert cell
{
const svg = d3.select(DOM.svg(width, 1500))
.attr("viewBox", "0 0 960 1500")
.style("width", "100%")
.style("height", "auto");
const path = d3.geoPath(projection);
svg.append("g")
.selectAll("circle")
.data(spreadConstituencies)
.enter().append("circle")
.attr("fill", d => (d.properties.results.region_name == "London") ? "red" : "black")
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("r", d => d.properties.radius)
.style("stroke", "white")

return svg.node();
}
Insert cell
constituencies = {
let output = topojson.feature(wpc_borders, wpc_borders.objects.wpc);
for (let feat of output.features) {
const centroid = projection(turf.centroid(feat.geometry).geometry.coordinates);
feat.properties.centroid = centroid;
feat.properties.results = election_results.find(d => d.ons_id == feat.properties.PC_ID);
feat.properties.radius = 4.5;
}
return output.features;
}
Insert cell
applySimulation = (nodes) => {
const simulation = d3.forceSimulation(nodes)
.force("cx", d3.forceX().x(d => width / 2).strength(0.02))
.force("cy", d3.forceY().y(d => width * (5/8) / 2).strength(0.02))
.force("x", d3.forceX().x(d => d.properties.centroid ? d.properties.centroid[0] : 0).strength(0.3))
.force("y", d3.forceY().y(d => d.properties.centroid ? d.properties.centroid[1] : 0).strength(0.3))
.force("charge", d3.forceManyBody().strength(-1))
.force("collide", d3.forceCollide().radius(d => d.properties.radius * 1.253).strength(1))
.stop()

let i = 0;
while (simulation.alpha() > 0.01 && i < 200) {
simulation.tick();
i++;
console.log(`${Math.round(100*i/200)}%`)
}

return simulation.nodes();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
projection = d3.geoAzimuthalEqualArea().rotate([2, -58]).scale(8000)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
turf = require("@turf/turf@5")
Insert cell
import {rectCollide} from "@lvngd/rectangular-collision-detection"

Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more