canvas = {
const height = width
const context = DOM.context2d(width, width);
const nPts = 30
const scale = d3.scaleLinear()
.domain([0, nPts])
.range([0, width])
context.canvas.update = mouse => {
let {left: cx, top: cy} = context.canvas.getBoundingClientRect();
let {x: mx, y: my} = mouse;
mx -= cx;
my -= cy;
context.clearRect(0, 0, width, height);
context.beginPath()
const b1 = d3.range(nPts).map(pt => {
const x = scale(pt),
y = 0
context.moveTo(x, y);
context.arc(x, y, 4, 0, 2*Math.PI);
return {x,y}
})
const b2 = d3.range(nPts).map(pt => {
const x = scale(pt),
y = width
context.moveTo(x, y);
context.arc(x, y, 4, 0, 2*Math.PI);
return {x,y}
})
context.fillStyle = "black"
context.fill()
context.beginPath()
const l1 = d3.range(nPts).map(pt => {
const x = mx/nPts * pt
const y = my/nPts * pt
context.moveTo(x, y);
context.arc(x, y, 4, 0, 2*Math.PI);
return {x,y}
})
const l2 = d3.range(nPts).map(pt => {
const x = width - (mx/nPts * pt)
const y = width - (my/nPts * pt)
context.moveTo(x, y);
context.arc(x, y, 4, 0, 2*Math.PI);
return {x,y}
})
context.fillStyle = "black"
context.fill()
for (let i = 0 ; i < nPts ; i++) {
const start = b1[i]
const end = l1[nPts-1-i]
context.beginPath();
context.moveTo(start.x, start.y);
context.lineTo(end.x, end.y);
context.stroke();
}
for (let i = 0 ; i < nPts ; i++) {
const start = b2[i]
const end = l2[i]
context.beginPath();
context.moveTo(start.x, start.y);
context.lineTo(end.x, end.y);
context.stroke();
}
};
return context.canvas;
}