Public
Edited
Aug 1, 2023
4 forks
11 stars
Insert cell
Insert cell
{
const width = 960;
const height = 500;

const projection = d3
.geoAlbers()
.rotate([120, 0])
.center([0, 37.7])
.scale(2700);

const svg = d3.create("svg").attr("width", width).attr("height", height);
yield svg.node();
const path = svg.append("path").attr("fill", "#ccc").attr("stroke", "#333");

const coordinates0 = polygon.coordinates[0].map(projection);
const coordinates1 = circle(coordinates0);
const d0 = "M" + coordinates0.join("L") + "Z";
const d1 = "M" + coordinates1.join("L") + "Z";

loop();

async function loop() {
await path
.attr("d", d0)
.transition()
.duration(5000)
.attr("d", d1)
.transition()
.delay(5000)
.attr("d", d0)
.end();
requestAnimationFrame(loop);
}

function circle(coordinates) {
const circle = [];
let length = 0;
const lengths = [length];
let p0 = coordinates[0];
let p1;
let x;
let y;
let i = 0;
const n = coordinates.length;

// Compute the distances of each coordinate.
while (++i < n) {
p1 = coordinates[i];
x = p1[0] - p0[0];
y = p1[1] - p0[1];
lengths.push((length += Math.sqrt(x * x + y * y)));
p0 = p1;
}

const area = d3.polygonArea(coordinates);
const radius = Math.sqrt(Math.abs(area) / Math.PI);
const centroid = d3.polygonCentroid(coordinates);
const angleOffset = -Math.PI / 2; // TODO compute automatically
let angle;
const k = (2 * Math.PI) / lengths[lengths.length - 1];

// Compute points along the circle’s circumference at equivalent distances.
i = -1;
while (++i < n) {
angle = angleOffset + lengths[i] * k;
circle.push([
centroid[0] + radius * Math.cos(angle),
centroid[1] + radius * Math.sin(angle)
]);
}

return circle;
}
}
Insert cell
polygon = FileAttachment("california.json").json()
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