chartWithFaster = {
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("faster")
.scale({
domain: ["Arquero", "duckDB", "nativeJS"],
range: ["#1f77b4", "#ff7f0e", "#2ca02c"]
}),
vl.detail().fieldN("index"),
vl.opacity().if(hover, vl.value(1)).value(0.3),
vl.y().fieldQ("norm_val").axis(null),
vl.tooltip([...attribs, "comb", "faster"])
);
const points = line
.markCircle()
.select(hover)
.encode(vl.size().if(hover, vl.value(50)).value(5));
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));
const ticks = Array.from({ length: 3 }).map((_, i) =>
tick((height / (3 - 1)) * i)
);
return vl
.layer(base, line, points, ...ticks)
.data(data_)
.transform(
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();
}