diff options
| author | tv <tv@krebsco.de> | 2026-10-31 22:52:51 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-10-31 22:52:51 +0100 |
| commit | daa05b40d31a3559134ecdcb0d4e1f1b0d3b0017 (patch) | |
| tree | e57ae2c9661fac809e62cb8671b196e565ec956d /src/api/dashboard/dashboard.html | |
| parent | 92803b18e699d938ea7a302e4a45d91f852a4e1c (diff) | |
dashboard: updated labels breath
Diffstat (limited to 'src/api/dashboard/dashboard.html')
| -rw-r--r-- | src/api/dashboard/dashboard.html | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/src/api/dashboard/dashboard.html b/src/api/dashboard/dashboard.html index e584f48..ccf4892 100644 --- a/src/api/dashboard/dashboard.html +++ b/src/api/dashboard/dashboard.html @@ -597,6 +597,25 @@ function upright(attrs) { function text(node, content) { if (node.textContent !== content) node.textContent = content; } +// A label on the map: its text, breathing once when it changed (not when new), as the +// connection's dot does: its underlay, in the shape of the new text, glows and fades. +// An animation of its own, not a class: every render sets the label's attributes. +const calm = matchMedia("(prefers-reduced-motion: reduce)"); +function label(node, content) { + if (node.textContent === content) return; + const before = node.textContent; + node.textContent = content; + if (!before || calm.matches || !node.animate) return; + const colours = getComputedStyle(document.documentElement); + const panel = colours.getPropertyValue("--panel").trim(); + const glow = "color-mix(in srgb, " + colours.getPropertyValue("--self").trim() + " 45%, " + + panel + ")"; + node.animate([ + { stroke: panel, strokeWidth: "4px" }, + { stroke: glow, strokeWidth: "7px", offset: .3 }, + { stroke: panel, strokeWidth: "4px" }, + ], { duration: 900, easing: "ease-in-out" }); +} // A tooltip whose text changes under the pointer goes and comes back (the ages in it // change on every render): its new text waits until the pointer leaves. const tooltipsDue = new WeakMap(); @@ -742,13 +761,13 @@ function renderGraph() { const along = Math.min(length / 2, Math.max(36, length * .3)); const t = (line.used ? along : Math.max(24, along * .6)) / length; const out = line.used ? -4 : Math.sign(side) * 9; - const label = drawing("rtt " + key + " " + i, "text", upright({ + const rtt = drawing("rtt " + key + " " + i, "text", upright({ x: p.x + (q.x - p.x) * t + ox + nx * out, y: p.y + (q.y - p.y) * t + oy + ny * out + (line.used ? 0 : 3), "text-anchor": "middle", "font-size": line.used ? 11 : 9, fill: line.used ? "var(--fg)" : "var(--muted)" })); - text(label, ms(line.rttMs)); - labels.push(label); + label(rtt, ms(line.rttMs)); + labels.push(rtt); } }); tooltip(covering, descriptions.join("\n")); @@ -792,10 +811,10 @@ function renderGraph() { const pin = pinned.has(id) ? [drawing("pin " + id, "circle", { cx: p.x, cy: p.y, r: 2, fill: member.self || reported ? "var(--panel)" : "var(--fg)", "pointer-events": "none" })] : []; - const label = drawing("name " + id, "text", upright({ x: p.x + 10, y: p.y + 4, + const nameLabel = drawing("name " + id, "text", upright({ x: p.x + 10, y: p.y + 4, "font-size": 12, fill: "var(--fg)", cursor: "pointer" }), pressed); - text(label, name(id)); - children.push(circle, ...pin, label); + label(nameLabel, name(id)); + children.push(circle, ...pin, nameLabel); } show(document.getElementById("view"), children); } |
