Public
Edited
Nov 12, 2022
1 star
Insert cell
Insert cell
{
const height = 600;
const icon = paths[2];
const scale = 1.5;
const subdivisions = 120;
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [-width/2, -height/2, width, height])
.attr("transform", `translate(${(-icon.width*scale)/2},${(-icon.height*scale)/2}) scale(${scale}, ${scale})`);
const path = svg.append("g")
.append("path")
.attr("d", icon.paths[0].d)
.attr("fill", "transparent")
// .attr("stroke", "black")
.attr("stroke-width", "0.5px")
.attr("opacity", 0.2)
const totalLength = path.node().getTotalLength();

for (let i=0; i < subdivisions; i++) {
const radius = Math.random() * 12 + 1;
const distance = i * totalLength / subdivisions + Math.random() * totalLength / subdivisions;
const point = path.node().getPointAtLength(distance);

// get a vector and use it to translate the center}
const point2 = path.node().getPointAtLength(distance + 0.1);
const vector = vec(point, point2);
const translatedCenter = translate(point, vector.normal, radius, -1);

const circle = svg.append("circle")
.attr("cx", translatedCenter.x)
.attr("cy", translatedCenter.y)
.attr("r", radius)
.attr("opacity", Math.random())
.attr("i", i)
.attr("fill", color_scale(i/subdivisions));
};


yield svg.node();
let ease = false;
while (true) {
yield svg.node();

const pos = [...Array(subdivisions).keys()].map(d => {
const distance = d * totalLength / subdivisions + Math.random() * totalLength / subdivisions * 0.5;
const point = path.node().getPointAtLength(distance);

// get a vector and use it to translate the center
const point2 = path.node().getPointAtLength(distance + 0.01);
const vector = vec(point, point2);
const radius = Math.random()*15+1;
const translatedCenter = translate(point, vector.normal, radius, -1);

return {x: translatedCenter.x, y: translatedCenter.y, r: radius}
});


await d3.selectAll("circle").transition()
.ease(d3.easeBackOut)
.duration(4000)
.attr("r", (d,i) => pos[i].r)
.attr("cx", (d,i) => pos[i].x)
.attr("cy", (d,i) => pos[i].y)
.end();

ease = !ease;
}

}
Insert cell
color_palette = ["#F7D031", "#F9A326", "#F98321", "#FC5D1F", "#0099FA", "#0372E2", "#024CB7", "#002F87"]
Insert cell
color_scale = d3.interpolateRgbBasis(color_palette)
Insert cell
d3.color(color_palette[0])
Insert cell
paths = [
{
name: "house",
paths: [
{
d: "M197 81L99 1L1 81 M34 77V122V167H99H164V122V77",
}
],
height: 168,
width: 198
},
{
name: "person",
paths: [
{
d : "M102.5 35.1136C102.5 54.2317 87.0523 69.7272 68 69.7272C48.9477 69.7272 33.5 54.2317 33.5 35.1136C33.5 15.9955 48.9477 0.5 68 0.5C87.0523 0.5 102.5 15.9955 102.5 35.1136Z M135 149.484C135 111.252 105.003 80.2597 68 80.2597C30.9969 80.2597 1 111.252 1 149.484"
}
],
height: 150,
width: 136
},
{
name: "household",
paths: [
{
d: "M180.663 111.162C180.663 128.167 166.716 141.962 149.5 141.962C132.284 141.962 118.337 128.167 118.337 111.162C118.337 94.1566 132.284 80.3615 149.5 80.3615C166.716 80.3615 180.663 94.1566 180.663 111.162Z M210.112 213.111C210.112 179.032 182.975 151.405 149.5 151.405C116.025 151.405 88.8878 179.032 88.8878 213.111 M298 120L149.5 1L1 120 M51 114V181V248H149.5H248V181V114"
}
],
width: 299,
height: 249
}
]
Insert cell
<svg width="299" height="249" viewBox="0 0 299 249" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M180.663 111.162C180.663 128.167 166.716 141.962 149.5 141.962C132.284 141.962 118.337 128.167 118.337 111.162C118.337 94.1566 132.284 80.3615 149.5 80.3615C166.716 80.3615 180.663 94.1566 180.663 111.162Z" fill="white" stroke="black"/>
<path d="M210.112 213.111C210.112 179.032 182.975 151.405 149.5 151.405C116.025 151.405 88.8878 179.032 88.8878 213.111" stroke="black"/>
<path d="M298 120L149.5 1L1 120" stroke="black"/>
<path d="M51 114V181V248H149.5H248V181V114" stroke="black"/>
</svg>

Insert cell
<svg width="136" height="150" viewBox="0 0 136 150" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M102.5 35.1136C102.5 54.2317 87.0523 69.7272 68 69.7272C48.9477 69.7272 33.5 54.2317 33.5 35.1136C33.5 15.9955 48.9477 0.5 68 0.5C87.0523 0.5 102.5 15.9955 102.5 35.1136Z" fill="white" stroke="black"/>
<path d="M135 149.484C135 111.252 105.003 80.2597 68 80.2597C30.9969 80.2597 1 111.252 1 149.484" stroke="black"/>
</svg>

Insert cell
<svg width="198" height="168" viewBox="0 0 198 168" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M197 81L99 1L1 81 M34 77V122V167H99H164V122V77" stroke="black"/>
</svg>

Insert cell
import {vec, translate} from "@daformat/distributing-circles-around-a-shape"
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