function newchart({ height = 250 } = {}) {
const context = DOM.context2d(width, height),
canvas = context.canvas;
canvas.context = context;
const events = [];
let types = [],
locations = [];
let lastPointers = [];
const h = d3.scaleOrdinal().range(d3.range(20).map(i => 12 * i + 16));
const timer = d3.timer(tick);
timer.stop();
canvas.update = function(event, pointers) {
lastPointers = pointers || d3.pointers(event, canvas);
if (event) events.push({ date: +new Date(), event });
tick();
};
function tick() {
const now = +new Date();
while (events.length > 0 && events[0].date < now - 1000) events.shift();
if (!events.length) clean();
else timer.restart(tick);
paint();
}
function clean() {
lastPointers = [];
paint();
timer.stop();
}
function paint() {
context.clearRect(0, 0, width, height);
context.fillStyle = "#333";
context.fillText(`.on(…)`, 2, 8);
context.fillStyle = "#777";
for (const type of canvas.__on.map(d => d.type)) {
context.fillText(`${type}`, 2, h(type) + 8);
}
for (const [type, list] of d3.group(events, d => d.event.type)) {
list.reverse();
context.fillStyle = timeColor(list[0].date);
context.fillRect(0, h(type), 120, 10);
for (let i = 0; i < list.length; i++) {
context.fillStyle = timeColor(list[i].date);
context.fillRect(122 + 12 * i, h(type), 10, 10);
}
context.fillStyle = "black";
context.fillText(`${type}`, 2, h(type) + 8);
}
context.fillStyle = "black";
for (const pointer of lastPointers) {
context.setLineDash([2, 2]);
context.lineWidth = 0.5;
context.beginPath();
context.moveTo(pointer[0], 0);
context.lineTo(pointer[0], height);
context.moveTo(0, pointer[1]);
context.lineTo(width, pointer[1]);
context.stroke();
context.setLineDash([]);
context.lineWidth = 0.25;
context.beginPath();
context.moveTo(...pointer);
const sx = pointer[0] < width / 2 ? 1 : -1;
const sy = pointer[1] < height / 2 ? 1 : -1;
context.lineTo(pointer[0] + sx * 23, pointer[1] + sy * 23);
context.stroke();
context.textAlign = sx > 0 ? "start" : "end";
context.fillText(
`${+pointer[0].toFixed(3)}, ${+pointer[1].toFixed(3)}`,
pointer[0] + sx * 28,
pointer[1] + sy * 26
);
context.textAlign = "start";
}
if (context.canvas.callback) context.canvas.callback(context);
}
setTimeout(paint, 10);
return canvas;
}