Published
Edited
May 19, 2020
2 forks
Importers
40 stars
Insert cell
Insert cell
{
const node = svg`<svg viewBox="0 0 ${width} ${height}">
<path fill="none" stroke="#000" stroke-width="1" d="${line}" />
<line fill="none" stroke="#ccc" stroke-width="2" y1="0" y2="${height}" />
${data.map(d => svg`<circle r=2.5 cx=${d[0]} cy=${d[1]}>`)}
<circle id="intersection" fill="red" r="5" />
</svg>`;

const solver = solve(line);

return d3
.select(node)
.on("mousemove", move)
.call(move)
.node();

function move() {
const x = d3.event ? d3.mouse(node)[0] : width / 3;

d3.select(node)
.select("line")
.attr("x1", x)
.attr("x2", x);

d3.select(node)
.select("#intersection")
.attr("cx", x)
.attr("cy", solver(x) || -10);
}
}
Insert cell
// the solver draws the path on a 1 pixel-wide canvas, then looks for the first tainted pixel
solve = {
const context = DOM.context2d(1, height, 1);
return function(line) {
const p = new Path2D(line);
return function(x) {
context.save();
context.clearRect(0, 0, 1, height);
context.translate(-x, 0);
context.stroke(p);
context.restore();
const data = context.getImageData(0, 0, 1, height).data;
for (let y = 0; y < height; y++)
if (data[4 * y + 3]) {
return y + (1 - data[4 * y + 3] / 255);
}
};
};
}
Insert cell
data = Array.from({ length: 20 }, (_, i) => [
((i + .5) * width) / 21,
Math.random() * height
])
Insert cell
line = d3.line().curve(d3.curveBasis)(data)
Insert cell
d3 = require("d3@5")
Insert cell
height = 300
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more