Public
Edited
Nov 27, 2024
3 stars
Insert cell
Insert cell
chart = {
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.style("background-color", "#faf9f9")

const g = svg.append("g")
.attr("transform", `translate(${width/2}, ${height/2})`)

// use a pie chart to create backgrounds or "sheets of kimono fabric" for each month
const pieChart = g.selectAll(".large-pie")
.data(arcs)
.join("path")
.classed("large-pie", true)
.attr("fill", 'none')
.attr("stroke", 'white')
.attr("stroke-width", 5)
.attr("stroke-opacity", 1)
.attr("d", d => arc(d))
.attr("id", (d, i) => `monthArc_${i}`) // need this for the text on arcs

// add labels for the months on the arcs
// code based on https://www.visualcinnamon.com/2015/09/placing-text-on-arcs/
const monthLabels = g.selectAll(".month-label")
.data(months)
.join("text")
.classed("month-label", true)
.attr("x", 31)
.attr("dy", -20)
.append("textPath")
.attr("xlink:href", (d, i) => `#monthArc_${i}`)
.text(d => d.name);

// add a smaller pie chart on top of the bigger one so that you can fill just part of
// the pie arcs with colours
const smallPieChart = g.selectAll("small-pie")
.data(arcs)
.join("path")
.classed("small-pie", true)
.attr("fill", "white")
//.attr("fill", d => colourScaleMonths[d.data.name]) // to fill with one of the colours for the corresponding month - didn't look very good
.attr("opacity", 1)
.attr("d", d => arcSmall(d))

// blur filter for the blurry circles behind the flowers
const defs = svg.append("defs")
defs.append("filter")
.attr("id", "blur2")
.attr("width", "200%")
.attr("height", "200%")
.attr("x", "-60%")
.attr("y", "-60%")
.attr("color-interpolation-filters","sRGB")
.append("feGaussianBlur")
.attr("in","SourceGraphic")
.attr("stdDeviation","10")

// groups for the 2 colourful circles behind each petal
const circlesG = g.selectAll("g")
.data(months)
.join("g")
.attr("transform", d => `translate(
${d3.pointRadial(x(d.name)+ x.bandwidth()/2, 230)[0]},
${d3.pointRadial(x(d.name) + x.bandwidth()/2, 230)[1]}
)`)

// the circles
const circles = circlesG.selectAll('circle')
.data(d => circlesDataExtended[d.name])
.join("circle")
.attr('transform', (d,i) => `rotate(${180 * i})`)
.attr("r", 30)
.attr("cx", 14)
.style("mix-blend-mode", "multiply")
.style("fill", d => d)
.style("filter", "url(#blur2)")

// the flowers
const flowers = circlesG.selectAll('path')
.data(d3.range(8))
.join('path')
.attr('transform', (d,i) => "scale(0.3)rotate(" + (360/8 * i) + ")")
.style('stroke', '#fff')
.style('fill', 'none')
.style("stroke-width", 2)
.attr('d', petal)

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
arcs = pie(months)
Insert cell
Insert cell
Insert cell
x = d3.scaleBand()
.domain(months.map(d => d.name))
.range([0, 2 * Math.PI])
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
petal = [
'M0,0',
'L-20,15',
'C0,30 -20,60 -50,50',
'C-60,100 -10,80 0,110',
'C10,80 60,100 50,50',
'C20,60 0,30 20,15',
'Z'
].join(" ")
Insert cell
petalPaths = [
'M0 0 C50 50 50 100 0 100 C-50 100 -50 50 0 0',
'M-35 0 C-25 25 25 25 35 0 C50 25 25 75 0 100 C-25 75 -50 25 -35 0',
'M0,0 C50,40 50,70 20,100 L0,85 L-20,100 C-50,70 -50,40 0,0',
'M0 0 C50 25 50 75 0 100 C-50 75 -50 25 0 0',
petal,
'M0 0 C40 30 60 60 0 100 C-60 60 -40 30 0 0',
'M0 0 C30 50 50 90 10 100 L0 90 L-10 100 C-50 90 -30 50 0 0',
'M0 0 C40 20 60 60 20 100 C10 110 -10 110 -20 100 C-60 60 -40 20 0 0 Z'
]
Insert cell
Insert cell
Insert cell
<link href="https://fonts.googleapis.com/css2?family=Dancing+Script&family=Sacramento&display=swap" rel="stylesheet"><style>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Archivo+Black&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Della+Respira&display=swap" rel="stylesheet">

h1, svg {
font-family: 'Sacramento', cursive;
fill: #e5e5e5;
font-size: 26px;
font-weight: bold;
}
text.initials {
font-family: "Archivo Black", sans-serif;
font-family: "Della Respira", serif;
font-weight: normal;
line-height: 1;
margin: 0;
padding: 0;
font-size: 30px;
}
</style>
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