{
const htmlContent = html`
<style type="text/css">
.dot {
opacity: 0.7;
fill: steelblue;
}
</style>
<div><svg width="800" height="300">
<circle cx="150" cy="150" r="100" style="fill: none; stroke: grey; stroke-dasharray: 1,3"/>
<g transform="translate(150, 150)"></g>
</svg></div>
<button>Update data</button>
`
const container = d3.select(htmlContent);
const svg = container.select("svg");
const button = container.select("button");
const r = svg.select("circle").attr("r");
let data = [0, 0, 0];
update();
button.on("click", update);
function getAngle(circ) {
return Math.atan2(circ.attr("cy"), circ.attr("cx"));
}
function getInterpolator(cur, d) {
let currentAngle = getAngle(cur);
if (d - currentAngle > Math.PI) { d -= 2 * Math.PI; }
else if (currentAngle - d > Math.PI) { d += 2 * Math.PI; }
return d3.interpolate(currentAngle, d);
}
function getCurrentAngle(el) {
let x = d3.select(el).attr('cx');
let y = d3.select(el).attr('cy');
return Math.atan2(y, x);
}
function update() {
for (let i = 0; i < 3; ++i) {
data[i] = Math.random() * 2 * Math.PI;
}
svg.select("g")
.selectAll("circle")
.data(data)
.join("circle")
.attr("r", 7)
.attr("class", "dot")
.transition()
.duration(1000)
.tween("circumference", function(d) {
const cur = d3.select(this);
const currentAngle = getAngle(cur);
let interpolator = getInterpolator(cur, d);
return (t) => {
const angle = interpolator(t);
cur.attr("cx", r * Math.cos(angle));
cur.attr("cy", r * Math.sin(angle));
};
})
}
return htmlContent;
}