chart = {
const div = html`<div style="position:relative;">`;
const canvas = d3.select(div)
.selectAll("canvas")
.data(data)
.enter().append(() => DOM.context2d(width, step, 1).canvas)
.style("position", "absolute")
.style("image-rendering", "pixelated")
.style("top", (d, i) => `${i * (step + 1) + margin.top}px`)
.property("context", function() { return this.getContext("2d"); })
.each(horizon);
const svg = d3.select(div.appendChild(DOM.svg(width, height)))
.style("position", "relative")
.style("font", "10px sans-serif");
const gX = svg.append("g");
svg.append("g")
.selectAll("text")
.data(data)
.join("text")
.attr("x", 4)
.attr("y", (d, i) => (i + 0.5) * (step + 1) + margin.top)
.attr("dy", "0.35em")
.text((d, i) => i);
const rule = svg.append("line")
.attr("stroke", "#000")
.attr("y1", margin.top - 6)
.attr("y2", height - margin.bottom - 1)
.attr("x1", 0.5)
.attr("x2", 0.5);
svg.on("mousemove touchmove", () => {
const x = d3.mouse(svg.node())[0] + 0.5;
rule.attr("x1", x).attr("x2", x);
});
function horizon(d) {
const {context} = this;
const {length: k} = d;
if (k < width) context.drawImage(this, k, 0, width - k, step, 0, 0, width - k, step);
context.fillStyle = "#fff";
context.fillRect(width - k, 0, k, step);
for (let i = 0; i < overlap; ++i) {
context.save();
context.translate(width - k, (i + 1) * step);
context.fillStyle = color(i);
for (let j = 0; j < k; ++j) {
context.fillRect(j, y(d[j]), 1, -y(d[j]));
}
context.restore();
}
}
div.update = data => {
canvas.data(data).each(horizon);
gX.call(xAxis);
};
return div;
}