function minimap(root, leaf, initial, current) {
const container = svg`<svg
width=${width}
height=${height}
viewBox="-1 -1 ${width + 1} ${height + 2}"
/>
`;
const elements = [];
let el = leaf;
while (el !== root.parentElement) {
elements.push(el);
el = el.parentElement;
}
const x = d3
.scaleLinear()
.domain([0, d3.max(elements, el => el.offsetWidth)])
.range([0, width]);
const y = d3
.scaleLinear()
.domain([0, d3.max(elements, el => el.offsetHeight)])
.range([0, height]);
if (initial && current) {
const clientRect = initial.target.getBoundingClientRect();
const ex = d3
.scaleLinear()
.domain([clientRect.left, clientRect.right])
.range([0, initial.target.offsetWidth]);
const ey = d3
.scaleLinear()
.domain([clientRect.top, clientRect.bottom])
.range([0, initial.target.offsetHeight]);
container.appendChild(svg`
<circle
cx="${x(ex(initial.clientX))}"
cy="${y(ey(initial.clientY))}"
r="4"
fill="blue"
/>
`);
container.appendChild(svg`
<circle
cx="${x(ex(current.clientX))}"
cy="${y(ey(current.clientY))}"
r="4"
fill="red"
/>
`);
}
let st = 0;
let sl = 0;
for (const el of elements) {
const { scrollTop, scrollLeft, offsetWidth, offsetHeight } = el;
const { borderColor } = window.getComputedStyle(el);
st += scrollTop;
sl += scrollLeft;
container.appendChild(svg`
<rect
x="${x(sl)}"
y="${y(st)}"
width="${x(offsetWidth)}"
height="${y(offsetHeight)}"
fill="none"
stroke="${borderColor}"
stroke-width="2"
/>
`);
}
return container;
}