First commit, done on M6 from the PLAN.MD
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
// Hand-drawn SVG helpers. Output is built from numbers only, so it is safe as innerHTML.
|
||||
|
||||
// Bigger chart for the end-of-term review: weekly samples over the whole term,
|
||||
// a gridline per year and per quarter of the value range.
|
||||
export function lineChart(values, { w = 260, h = 96, min = 0, max = 100, yearEvery = 52 } = {}) {
|
||||
const pad = 3;
|
||||
const n = values.length;
|
||||
const span = max - min || 1;
|
||||
const x = (i) => pad + (n > 1 ? (i / (n - 1)) * (w - 2 * pad) : 0);
|
||||
const y = (v) => h - pad - Math.min(1, Math.max(0, (v - min) / span)) * (h - 2 * pad);
|
||||
|
||||
const grid = [];
|
||||
for (let i = yearEvery; i < n; i += yearEvery) grid.push(`<line x1="${x(i).toFixed(1)}" y1="0" x2="${x(i).toFixed(1)}" y2="${h}"/>`);
|
||||
for (const f of [0.25, 0.5, 0.75]) grid.push(`<line x1="0" y1="${(h * f).toFixed(1)}" x2="${w}" y2="${(h * f).toFixed(1)}"/>`);
|
||||
|
||||
const pts = values.map((v, i) => `${x(i).toFixed(1)},${y(v).toFixed(1)}`).join(" ");
|
||||
return `<svg class="chart" viewBox="0 0 ${w} ${h}" width="100%" preserveAspectRatio="none" aria-hidden="true">` +
|
||||
`<g class="spark__grid">${grid.join("")}</g>` +
|
||||
(n > 1 ? `<polyline class="spark__line" points="${pts}" vector-effect="non-scaling-stroke"/>` : "") +
|
||||
`</svg>`;
|
||||
}
|
||||
|
||||
// Small line chart on graph paper. `values` are plotted evenly left to right.
|
||||
export function sparkline(values, { w = 84, h = 24, min = 0, max = 100 } = {}) {
|
||||
const grid = [];
|
||||
for (let x = 12; x < w; x += 12) grid.push(`<line x1="${x}" y1="0" x2="${x}" y2="${h}"/>`);
|
||||
for (const f of [0.25, 0.5, 0.75]) grid.push(`<line x1="0" y1="${h * f}" x2="${w}" y2="${h * f}"/>`);
|
||||
|
||||
let line = "";
|
||||
const n = values.length;
|
||||
if (n > 1) {
|
||||
const span = max - min || 1;
|
||||
const pts = values.map((v, i) => {
|
||||
const x = 2 + (i / (n - 1)) * (w - 4);
|
||||
const y = h - 2 - Math.min(1, Math.max(0, (v - min) / span)) * (h - 4);
|
||||
return [x.toFixed(1), y.toFixed(1)];
|
||||
});
|
||||
const last = pts[n - 1];
|
||||
line =
|
||||
`<polyline class="spark__line" points="${pts.map((p) => p.join(",")).join(" ")}"/>` +
|
||||
`<circle class="spark__dot" cx="${last[0]}" cy="${last[1]}" r="2"/>`;
|
||||
}
|
||||
return `<svg class="spark" viewBox="0 0 ${w} ${h}" width="${w}" height="${h}" aria-hidden="true">` +
|
||||
`<g class="spark__grid">${grid.join("")}</g>${line}</svg>`;
|
||||
}
|
||||
Reference in New Issue
Block a user