Terminal Bar Chart
A horizontal bar chart drawn with characters: a barX composite shape appends the title, the grid lines, the axis and the bars, with a figlet banner as an annotation.
js
const data = [1.9, 1.9, 1.6, 1.0, 0.4, 0.1];
const step = 3;
const marginX = 3;
const marginY = 3;
const plotWidth = 60;
const plotHeight = step * data.length;
const colors = ["#CC4A6A", "#6EBD41", "#D6B152", "#56ADD3", "#AC5ADA", "#7DDEBB"];
const renderer = cm.terminal({cols: plotWidth + marginX * 2, rows: plotHeight + marginY * 2});
const root = cm.flow().renderer(renderer);
function barX(flow, {x: X, y: Y, width, height, title}) {
const scaleX = d3.scaleLinear([0, d3.max(X)], [0, width]).nice();
const ticks = scaleX.ticks(5);
flow.datum(0).append(cm.text, {text: title, x: width / 2, y: -1, textAlign: "center", textBaseline: "bottom"});
const axis = flow.datum(0).append(cm.group, {x: 0, y: height});
axis.data(ticks).append(cm.link, {x: scaleX, x1: scaleX, y: 0, y1: -height - 1, stroke: {ch: ":"}});
axis.append(cm.link, {x: 0, x1: width, y: 0, y1: 0, stroke: {ch: "-"}});
axis.data(ticks).append(cm.text, {text: (d) => d.toFixed(1), x: scaleX, y: 1, textAlign: "center"});
flow.data(X).append(cm.rect, {
x: 0,
y: (_, i) => Y[i] * step,
width: scaleX,
height: step - 1,
fill: (_, i) => ({ch: "#", fg: colors[i % colors.length]}),
});
}
root
.append(cm.group, {x: marginX, y: marginY})
.data(data)
.append(barX, {
x: (d) => d,
y: (_, i) => i,
width: cm.constant(plotWidth),
height: cm.constant(plotHeight),
title: cm.constant("Terminal Bar Chart"),
});
root.append(cm.figlet, {
text: "2023",
x: marginX + plotWidth,
y: marginY + plotHeight,
textAlign: "end",
textBaseline: "bottom",
});
root.render();
document.body.append(renderer.node());