chart = {
let currentTransform = [width / 2, height / 2, height];
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);
let defs = svg.append("defs");
image_urls.forEach(function (url, i) {
defs
.append("pattern")
.attr("id", `image${i}`)
.attr("x", "0%")
.attr("y", "0%")
.attr("width", "100%")
.attr("height", "100%")
.attr("viewBox", "50 50 200 100")
.append("image")
.attr("x", "0%")
.attr("y", "0%")
.attr("width", "100%")
.attr("height", "100%")
.attr("href", url);
});
const g = svg.append("g");
g.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", ([x]) => x)
.attr("cy", ([, y]) => y)
.attr("r", radius)
.attr("stroke", "blue")
.attr("fill", (_, i) => `url(#image${i % image_urls.length}`);
function transition() {
const d = data[Math.floor(Math.random() * data.length)];
const i = d3.interpolateZoom(currentTransform, [...d, radius * 2 + 1]);
g.transition()
.delay(250)
.duration(i.duration)
.attrTween("transform", () => (t) => transform((currentTransform = i(t))))
.on("end", transition);
}
function transform([x, y, r]) {
return `
translate(${width / 2}, ${height / 2})
scale(${height / r})
translate(${-x}, ${-y})
`;
}
return svg.call(transition).node();
}