Public
Edited
May 3
1 fork
Insert cell
Insert cell
Insert cell
untitled = FileAttachment("Знімок екрана 2025-05-03 о 03.52.11.png").image()
Insert cell
Insert cell
flower = {

const width = 600;
const height = 500;
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", `0 0 ${width} ${height}`);

const flowerGroup = svg.append("g")
.attr("transform", `translate(${width/2}, ${height/2})`);
const petalColors = [
"#ff91a4", "#ffb6c1", "#ff77a9", "#ffaec0",
"#ff91a4", "#ffb6c1", "#ff77a9", "#ffaec0"
];

const petalData = [70, 60, 50, 75, 50, 50, 50];
const pie = d3.pie().sort(null).value(d => d);

const pieData = pie(petalData);

// Перший ряд (більші пелюстки)
flowerGroup.selectAll('.petal-outer')
.data(pieData)
.join("path")
.attr("class", "petal-outer")
.attr("transform", d => r((d.startAngle + d.endAngle) / 2))
.attr("d", d => petalPath(d, 60, 3))
.attr("fill", (d, i) => petalColors[i])
.attr("stroke", "#e66980")
.attr("stroke-width", 1.5);

// Другий ряд (менші пелюстки)
const pieDataInner = pie(petalData.map(d => d * 0.8));

flowerGroup.selectAll('.petal-inner')
.data(pieDataInner)
.join("path")
.attr("class", "petal-inner")
.attr("transform", d => r((d.startAngle + d.endAngle) / 2 + Math.PI / petalData.length))
.attr("d", d => petalPath(d, 40, 2))
.attr("fill", (d, i) => petalColors[(i + 2) % petalColors.length])
.attr("stroke", "#e66980")
.attr("stroke-width", 1.5)
.attr("opacity", 0.9);


// Коло в центрі квітки
flowerGroup.append("circle")
.attr("cx", 0)
.attr("cy", 0)
.attr("r", 35)
.attr("fill", "#ff9900");

return svg.node();
}
Insert cell
//radius - довжина, scaleFactor - ширина
function petalPath(d, radius, scaleFactor = 2, ) {
const angle = (d.endAngle - d.startAngle) / scaleFactor, //половина сектора (щоб не була надто широкою)
s = polarToCartesian(-angle, radius),
e = polarToCartesian(angle, radius),
r = radius,
m = {x: radius + r, y: 0}, //вершина пелюстки
c1 = {x: radius + r / 2, y: s.y},
c2 = {x: radius + r / 2, y: e.y};
return "M0,0Q" +
Math.round(c1.x) + "," +
Math.round(c1.y * 2) + " " +
Math.round(m.x + r) + "," +
Math.round(m.y) +
"Q" +
Math.round(c2.x) + "," +
Math.round(c2.y * 2) + " " +
Math.round(0) + "," +
Math.round(0) +
"Z";
}

Insert cell
function polarToCartesian(angle, radius) {
return {
x: Math.cos(angle) * radius,
y: Math.sin(angle) * radius
};
}
Insert cell
function r(angle) {
return "rotate(" + (angle / Math.PI * 180) + ")";
}
Insert cell
Insert cell
untitled2 = FileAttachment("Знімок екрана 2025-05-03 о 14.14.38.png").image()
Insert cell
Insert cell
untitled1 = FileAttachment("Знімок екрана 2025-05-03 о 03.55.13.png").image({width:400})
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