startLoop = {
const startLoop = () => {
d3.select("svg")
.selectAll(".rect")
.data(items, (d) => d.id)
.join(
(enter) => enter.append("rect").call(applyStyles),
(update) => update.call(applyStyles),
(exit) =>
exit.call((exit) => exit.transition().attr("opacity", 0).remove())
)
.attr("class", "rect");
return "Start";
};
invalidation.then(() => (mutable loopActive = false));
return startLoop;
async function applyStyles(selection) {
if (!loopActive || selection.empty()) return;
await selection
.transition()
.duration(1000)
.attr("opacity", 1)
.attr("y", 0)
.attr("x", startX)
.attr("width", radius)
.attr("height", radius)
.transition()
.duration(100)
.attr("fill", (d) => d.color)
.attr("opacity", 1)
.transition()
.duration(1000)
.ease(d3.easeQuadInOut)
.delay((d, i) => i * 250)
.attr("opacity", 1)
.attr("x", (d, i) => i * (radius + padding) + endX)
.attr("y", 0)
.attr("width", radius)
.attr("height", radius)
.transition()
.duration(2000)
.delay((d, i) => i * 100)
.attr("opacity", 0.2)
.on('end', (d, i) => console.log(`animation ${i + 1} completed `))
.end();
console.log(`all animations completed (${loopActive})`)
mutable items = createItems();
startLoop();
}
}