chart = {
const width = 400;
const height = 400;
const margin = {top: 30, right: 30, bottom: 30, left: 30};
const x = d3.scaleLinear()
.domain([-1, 1])
.range([margin.left, width - margin.right]);
const y = d3.scaleLinear()
.domain([-1, 1])
.range([height - margin.bottom, margin.top]);
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);
svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x));
svg.append("g")
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y));
let a = [-0.4, 0.4];
let b = [1, 0];
const arcPath = svg.append("path")
.attr("transform", `translate(${x(0)}, ${y(0)})`)
.attr("fill", "transparent")
.attr("stroke", "gray");
let l1 = svg.append('line')
.attr("x1", x(0))
.attr("y1", y(0))
.attr("x2", x(a[0]))
.attr("y2", y(a[1]))
.attr("stroke", color1);
let c1 = svg.append('circle')
.attr("cx", x(a[0]))
.attr("cy", y(a[1]))
.attr("r", 4)
.attr("fill", color1);
let l2 = svg.append('line')
.attr("x1", x(0))
.attr("y1", y(0))
.attr("x2", x(b[0]))
.attr("y2", y(b[1]))
.attr("stroke", color2);
let c2 = svg.append('circle')
.attr("cx", x(b[0]))
.attr("cy", y(b[1]))
.attr("fill", color2)
.attr("r", 4);
const arc = d3.arc()
.innerRadius(0)
.outerRadius(20)
.startAngle(0)
.endAngle(angle(a, b));
const angleFormat = d3.format(".0f");
const angleText = svg.append("text")
.attr("text-anchor", "middle")
.attr("alignment-baseline", "middle")
.attr("font-size", "12px")
.attr("transform", `translate(${x(0)}, ${y(0)})`);
const render = function() {
const clockwise = angle2(b, a) > 0;
const innerAngle = angle(a, b);
const startAngle = clockwise ? d3_angle(a) : d3_angle(b);
arcPath.attr("d", (arc.startAngle(0).endAngle(innerAngle))())
.attr("transform", `translate(${x(0)}, ${y(0)}) rotate(${startAngle * 180 / Math.PI})`);
let bis = normalize(bisect(a, b));
angleText
.text(angleFormat((innerAngle) * 180 / Math.PI) + "°")
.attr("transform", `translate(${x(bis[0] / 6)}, ${y(bis[1] / 6)})`);
}
const drag1 = d3.drag()
.on("drag", (event, d) => {
a = [x.invert(event.x), y.invert(event.y)];
a = normalize_vecs.length > 0 ? normalize(a) : a;
c1.attr("cx", x(a[0])).attr("cy", y(a[1]));
l1.attr("x2", x(a[0])).attr("y2", y(a[1]));
mutable vec_a = a;
render();
});
const drag2 = d3.drag()
.on("drag", (event, d) => {
b = [x.invert(event.x), y.invert(event.y)];
b = normalize_vecs.length > 0 ? normalize(b) : b;
c2.attr("cx", x(b[0])).attr("cy", y(b[1]));
l2.attr("x2", x(b[0])).attr("y2", y(b[1]));
mutable vec_b = b;
render();
});
c1.call(drag1);
c2.call(drag2);
render();
yield { svg: svg.node() };
}