Published
Edited
Sep 8, 2020
1 fork
6 stars
Insert cell
Insert cell
Insert cell
chart = {
const height = 400;
const hover = vl
.selectSingle()
.on("mouseover")
.nearest(true)
.empty("none");

const base = vl.markRule({ color: "#ccc" }).encode(
vl.x().fieldN("key"),
vl.detail().count()
);

const line = base.markLine().encode(
vl.color().fieldN("Species"),
vl.detail().fieldN("index"),
vl.opacity().if(hover, vl.value(1)).value(0.3),
vl.y().fieldQ("norm_val").axis(null),
vl.tooltip(attribs)
);

const points = line.markCircle()
.select(hover)
.encode(vl.size().if(hover, vl.value(50)).value(5));

// Generates a spec to show tick values at an specific value of y0
const tick = y0 =>
vl.layer(
base.markText({ style: "label" }).encode(vl.text().max("max")),
base.markTick({ style: "tick", size: 8, color: "#ccc" })
)
.encode(vl.y().value(y0));

// Create an array with *numTicks* ticks
const ticks = Array.from({ length: numTicks })
.map((_, i) => tick((height / (numTicks - 1)) * i));

return vl
.layer(base, line, points, ...ticks)
.data(data)
.transform(
vl.filter(attribs.map(a => `datum["${a}"] != null`).join(" && ")),
vl.window(vl.count().as("index")),
vl.fold(attribs),
vl.groupby("key").joinaggregate(vl.min("value").as("min"), vl.max("value").as("max")),
vl.calculate("(datum.value - datum.min) / (datum.max - datum.min)").as("norm_val"),
vl.calculate("(datum.min + datum.max) / 2").as("mid")
)
.config({
axisX: { domain: false, labelAngle: 0, tickColor: "#ccc", title: null },
view: { stroke: null },
style: {
label: { baseline: "middle", align: "right", dx: -5 },
tick: { orient: "horizontal" }
}
})
.width(width - 100)
.height(height)
.render();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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