citySunset = {
const svg = d3
.create("svg")
.attr("width", svgWidth)
.attr("height", svgHeight);
const defs = svg.append("defs");
const clipCircle = DOM.uid();
defs
.append("clipPath")
.attr("id", clipCircle.id)
.append("circle")
.attr("cx", svgWidth / 2)
.attr("cy", svgHeight / 2)
.attr("r", svgWidth / 2);
const colorGradient = DOM.uid();
defs
.append("linearGradient")
.attr("id", colorGradient.id)
.attr("gradientTransform", "rotate(90)")
.selectAll("stop")
.data([
{ offset: "5%", color: startColor },
{ offset: "95%", color: endColor }
])
.join("stop")
.attr("offset", (d) => d.offset)
.attr("stop-color", (d) => d.color);
const g = svg.append("g").attr("clip-path", clipCircle);
g.append("rect")
.attr("stroke", "none")
.attr("fill", colorGradient)
.attr("x", "0")
.attr("y", "0")
.attr("width", svgWidth)
.attr("height", svgHeight);
const tower = g
.append("g")
.attr("transform", `translate(${svgWidth * 0.25}, ${svgHeight * 0.15})`);
const towerData = getTowerData(towerWidth, towerHeight);
tower
.selectAll("line")
.data(towerData.lines)
.join("line")
.attr("stroke", "black")
.attr("stroke-width", (d) => d.strokeWidth)
.attr("x1", (d) => d.x1)
.attr("x2", (d) => d.x2)
.attr("y1", (d) => d.y1)
.attr("y2", (d) => d.y2);
tower
.selectAll("circle")
.data(towerData.circles)
.join("circle")
.attr("stroke", "none")
.attr("fill", (d) => d.fill || "black")
.attr("stroke", (d) => d.stroke || "none")
.attr("stroke-width", (d) => d.strokeWidth)
.attr("cx", (d) => d.cx)
.attr("cy", (d) => d.cy)
.attr("r", (d) => d.r);
g.append("rect")
.attr("stroke", "none")
.attr("fill", "white")
.attr("x", "0")
.attr("y", svgHeight * cloudHeight)
.attr("width", svgWidth)
.attr("height", svgHeight * (1 - cloudHeight));
svg
.append("circle")
.attr("fill", "none")
.attr("stroke", "black")
.attr("stroke-width", 10)
.attr("cx", svgWidth / 2)
.attr("cy", svgHeight / 2)
.attr("r", svgWidth / 2 - 5);
const clouds = g
.append("g")
.selectAll("circle")
.data(d3.range(svgWidth / 5))
.join("circle")
.attr("cx", (d) => d * 5)
.attr("cy", getRandomCloudHeight)
.attr("r", getRandomCloudRadius)
.attr("fill", "white");
yield svg.node();
while (animate) {
await clouds
.transition()
.duration(8000)
.delay(0)
.ease(d3.easeLinear)
.attr("cy", getRandomCloudHeight)
.attr("r", getRandomCloudRadius)
.end();
yield svg.node();
}
}