{
const $pdf = await RENDER_PDF();
const w = +$pdf.width;
const h = +$pdf.height;
const s = 2;
const ctx = DOM.context2d(w/s, h/s);
ctx.resetTransform();
ctx.scale(1/s, 1/s);
const radius = 10;
const { [3]: { paths } } = PATHS;
const yes = [];
const no = paths.slice();
for await (const action of actions(yield ctx.canvas)) {
const { type } = action;
if (type === 'add' || type === 'remove') {
let { x, y } = action;
x = s * x;
y = h - s * y;
const { src, dst } = {
add: { src: no, dst: yes },
remove: { src: yes, dst: no },
}[type];
for (let i=0; i<src.length; ++i) {
const path = src[i];
for (const point of path) {
if (Math.abs(point.x - x) < radius && Math.abs(point.y - y) < radius) {
console.log(point);
dst.splice(-1, 0, ...src.splice(i, 1));
break;
}
}
}
}
// ctx.clearRect(0, 0, w, h);
ctx.save();
ctx.resetTransform();
ctx.scale(1/s, 1/s);
ctx.globalCompositeOperation = 'copy';
ctx.drawImage($pdf, 0, 0, w, h);
ctx.globalCompositeOperation = 'source-over';
ctx.restore();
const options = [
{ lineWidth: 4, strokeStyle: 'black', paths },
{ lineWidth: 3, strokeStyle: `black`, paths: yes },
{ lineWidth: 3, strokeStyle: `white`, paths: no },
];
for (const { lineWidth, strokeStyle, paths } of options) {
for (const path of paths) {
ctx.beginPath();
ctx.moveTo(path[0].x, path[0].y);
for (let i=1, n=path.length; i<n; ++i) {
ctx.lineTo(path[i].x, h-path[i].y);
}
Object.assign(ctx, {
lineWidth,
strokeStyle,
});
ctx.stroke();
}
}
const { x, y } = action;
ctx.beginPath();
ctx.arc(x*s, y*s, 10, 0.0, 2*Math.PI);
ctx.strokeStyle = 'red';
ctx.stroke();
}
async function RENDER_PDF() {
const viewport = pdf.page.getViewport({
scale: 1,
});
const ctx = DOM.context2d(viewport.width, viewport.height);
// ctx.scale(1/s, 1/s);
await pdf.page.render({
canvasContext: ctx,
viewport,
}).promise;
return ctx.canvas;
}
function actions(target) {
return Generators.observe((notify) => {
target.addEventListener('mousedown', onmouse);
target.addEventListener('mouseup', onmouse);
notify({
action: null,
x: null,
y: null,
});
return () => {
target.removeEventListener('mousedown', onmouse);
target.removeEventListener('mousemove', onmouse);
target.removeEventListener('mouseup', onmouse);
}
function onmouse(e) {
e.preventDefault();
const { type } = e;
if (type === 'mousedown') {
target.addEventListener('mousemove', onmouse);
} else if (type === 'mouseup') {
target.removeEventListener('mousemove', onmouse);
}
const { ctrlKey } = e;
const [x, y] = d3.pointer(e);
notify({
type: ctrlKey ? 'add' : 'remove',
x,
y,
});
}
});
}
}