Public
Edited
Nov 12, 2022
4 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
totalFrames = 60 * duration
Insert cell
function delayedT(t, n = 1, maxN = 1) {
const dt = 1 / maxN;

let u = math.mapRange(
t,
((n - 1) * dt) / 4,
// 1 - dt,
1 - ((maxN - n) * dt) / 2,
0,
1,
true
);
u = eases.quadOut(u);
return u;
}
Insert cell
function drawShapes({
polygons,
cx,
cy,
r,
fill,
strokeWidth,
rotate = 0,
stroke,
t,
shouldRotate360deg
} = {}) {
polygons = Math.max(polygons, 1);
const maxEdges = polygons + 2;
const outershape = drawPolygonByRadius({
cx,
cy,
r,
fill,
stroke,
strokeWidth,
rotate: rotate,
edges: maxEdges,
rotateToFirstEdge: maxEdges % 2 == 0,
t: delayedT(t, polygons, polygons),
shouldRotate360deg
});
let shapes = [outershape];
const { side, rMin } = outershape;

shapes = [
...shapes,
...d3.range(polygons - 1, 0, -1).map((n) => {
return drawPolygonBySide({
edges: n + 2,
cx,
cy,
strokeWidth,
stroke,
rotate: rotate,
rotateToFirstEdge: n % 2 === 0,
side,
fill,
alignY: rMin,
v,
t: delayedT(t, n, polygons),
shouldRotate360deg
});
})
];
return shapes;
}
Insert cell
d3.range(4, 0, -1)
Insert cell
strokeWidth = 1 + strokeUV * 4
Insert cell
side2r(320, (2 * Math.PI) / 3)
Insert cell
function side2r(side, angle) {
const opp = side / 2;
const theta = angle / 2;
return opp / Math.sin(theta);
}
Insert cell
function r2side(r, angle) {
const theta = angle / 2;
return 2 * Math.sin(theta) * r;
}
Insert cell
function r2innerR(r, angle) {
const theta = angle / 2;
return Math.cos(theta) * r;
}
Insert cell
function drawPolygonBySide({
cx = 0,
cy = 0,
side,
fill = "none",
edges = 3,
rotate = 0,
stroke = `hsl(0, 0%, 5%)`,
strokeWidth = 1,
rotateToFirstEdge = false,
alignY,
v,
t = 0,
shouldRotate360deg
} = {}) {
edges = Math.max(3, edges);
const segmentAngle = (Math.PI * 2) / edges;
const r = side2r(side, segmentAngle);

const animationAngle = shouldRotate360deg ? Math.PI * 2 : segmentAngle;

let dTheta = t * animationAngle + rotate - Math.PI / 2;

if (rotateToFirstEdge) {
dTheta = dTheta + segmentAngle / 2;
}

const innerR = r2innerR(r, segmentAngle);
const dy = v * (alignY - innerR);

const points = d3.range(edges).reduce((acc, i) => {
const angle = i * segmentAngle + dTheta;
const x = cx + r * Math.cos(angle);
const y = cy + r * Math.sin(angle) + dy;

return [...acc, [x, y]];
}, []);

const shape = htl.svg`<path
d=${`M${points.join(" ")}Z`}
fill=${fill}
stroke=${stroke}
stroke-width=${strokeWidth}
stroke-linejoin="round"
/>`;
return Object.assign(shape, { r });
}
Insert cell
function drawPolygonByRadius({
cx,
cy,
r,
fill = "none",
edges = 3,
rotate = 0,
stroke = `hsl(0, 0%, 5%)`,
strokeWidth = 1,
rotateToFirstEdge = false,
t = 0,
shouldRotate360deg
} = {}) {
edges = Math.max(3, edges);
const segmentAngle = (Math.PI * 2) / edges;
const animationAngle = shouldRotate360deg ? Math.PI * 2 : segmentAngle;
let dTheta = t * animationAngle + rotate - Math.PI / 2;

if (rotateToFirstEdge) {
dTheta = dTheta + segmentAngle / 2;
}

const points = d3.range(edges).reduce((acc, i) => {
const angle = i * segmentAngle + dTheta;
const x = cx + r * Math.cos(angle);
const y = cy + r * Math.sin(angle);

return [...acc, [x, y]];
}, []);

const shape = htl.svg`<path
d=${`M${points.join(" ")}Z`}
fill=${fill}
stroke=${stroke}
stroke-width=${strokeWidth}
stroke-linejoin="round"
/>`;
const side = r2side(r, segmentAngle);
const rMin = r2innerR(r, segmentAngle);
return Object.assign(shape, { side, rMin });
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
marginX = (w - size) / 2
Insert cell
marginY = (h - size) / 2
Insert cell
palette = ({
bg: "hsl(33, 74%, 90%)",
fg: "hsl(177, 100%, 34%)" //"hsl(29, 84%, 56%)"
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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