Public
Edited
Oct 28, 2023
13 stars
Insert cell
Insert cell
Plot.plot({
height: 280,
style: "cursor: pointer;",
marks: [
Plot.barX(rects, {
x1: "start",
x2: "end",
fill: "something",
y: "n",
inset: 1
}),
Plot.barX(
rects,
// use pointerY so that the squished voronoi of the (central) points is ~= to the rects
Plot.pointerY({
x1: "start",
x2: "end",
y: "n",
inset: 1,
fill: "red",

// render is called with the index filtered by the closest point (if any)
render(index, scales, values, dimensions, context, next) {
const [i] = index; // the pointer focus;

if (i !== undefined) {
// capture more of those. Assumes we don't facet
const X1 = values.channels.x1.value;
const X2 = values.channels.x2.value;
index = d3
.range(X1.length)
.filter((j) => X1[j] <= X1[i])
.filter((j) => X2[j] >= X2[i]);
}
return next(index, scales, values, dimensions, context);
}
})
),
Plot.text(rects, {
x1: "start",
x2: "end",
x: (d) => (d.start + d.end) / 2,
fill: "white",
text: (d) => `${d.start}..${d.end}`,
y: "n"
})
]
})
Insert cell
rects = {
const random = d3.randomLcg(42);
return d3.range(5).flatMap((n) =>
d3.range(2 ** n).map((i) => ({
n,
i,
start: i << (4 - n),
end: (i << (4 - n)) + 2 ** (4 - n),
something: random() < 0.9
}))
);
}
Insert cell
Insert cell
Plot.plot({
width,
height: 280,
style: "cursor: pointer;",
facet: { data: rects, x: (d) => d.i % 3 },
marks: [
Plot.frame(),
Plot.barX(rects, {
x1: "start",
x2: "end",
fill: "something",
y: "n",
inset: 1
}),
Plot.barX(
rects,
hoverRectangles({
x1: "start",
x2: "end",
y: "n",
inset: 1,
fill: "red"
})
),
Plot.text(rects, {
x1: "start",
x2: "end",
x: (d) => (d.start + d.end) / 2,
fill: "white",
text: (d) => `${d.start}..${d.end}`,
y: "n"
})
]
})
Insert cell
hoverRectangles = (options) =>
// use pointerY so that the squished voronoi of the (central) points is ~= to the rects
Plot.pointerY({
...options, // render is called with the index filtered by the closest point (if any)
render(index, scales, values, dimensions, context, next) {
const [i] = index; // pointer focus;
if (i !== undefined) {
// capture more of those.
const X1 = values.channels.x1.value;
const X2 = values.channels.x2.value;
index = context
.getMarkState(this)
.facets[index.fi ?? 0] // full index for the current facet
.filter((j) => X1[j] <= X1[i])
.filter((j) => X2[j] >= X2[i]);
}
return next(index, scales, values, dimensions, context);
}
})
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