Jiggly Recursive Circles
Nested circles that jiggle into a new offset and color scheme every two seconds, animated with d3-transition and an elastic ease. After Paul Buffa's Jiggly Map.
js
const size = 640;
const random = d3.randomUniform(-25, 25);
const schemes = [
"Viridis",
"Inferno",
"Magma",
"Plasma",
"Warm",
"Cool",
"Rainbow",
"CubehelixDefault",
"Blues",
"Greens",
"Oranges",
"Purples",
"Reds",
"BuPu",
"GnBu",
"OrRd",
"PuRd",
"RdPu",
"YlGnBu",
"YlOrRd",
];
const circles = d3.range(150, 4, -15).map((r) => ({x: size / 2, y: size / 2, r}));
const color = (scheme) => d3.scaleSequential([150, 0], d3[`interpolate${scheme}`]);
const svg = cm.svg`<svg ${{width: size, height: size, viewBox: [0, 0, size, size]}}>
<g ${{data: circles}}>
<circle ${{cx: (d) => d.x, cy: (d) => d.y, r: (d) => d.r, fill: (d) => color(schemes[0])(d.r), stroke: "black", stroke_width: 0.1}}/>
</g>
</svg>`;
function jiggle() {
const [dx, dy] = [random(), random()];
const fill = color(schemes[d3.randomInt(schemes.length)()]);
d3.select(svg)
.selectAll("g")
.data(circles)
.transition()
.duration(1000)
.delay((d, i) => i * 20)
.ease(d3.easeElastic)
.attr("transform", (d, i) => `translate(${i * dx}, ${i * dy})`)
.select("circle")
.attr("fill", (d) => fill(d.r));
}
jiggle();
setInterval(jiggle, 2000);
document.body.append(svg);