|
42 | 42 | .chart-box svg{ display:block; } |
43 | 43 | .legend{ display:flex; gap:6px 18px; flex-wrap:wrap; margin-top:12px; font-size:12.5px; color:#555; } |
44 | 44 | .legend .swatch{ display:inline-block; width:18px; height:3px; border-radius:2px; vertical-align:middle; margin-right:6px; } |
| 45 | + .legend [data-metric]{ cursor:default; } |
| 46 | + .chart-box svg [data-metric]{ transition:opacity .15s ease; } |
45 | 47 |
|
46 | 48 | .status{ font-size:13px; color:#888; } |
47 | 49 | .status.error{ border:1px solid #e3b3ae; background:#fbeae8; color:#8a2a22; |
|
194 | 196 | const color = COLORS[mi % COLORS.length]; |
195 | 197 | if (pts.length > 1) { |
196 | 198 | const path = pts.map((p, i) => (i ? "L" : "M") + p.x.toFixed(1) + " " + p.y.toFixed(1)).join(" "); |
197 | | - svg += `<path d="${path}" fill="none" stroke="${color}" stroke-width="2" stroke-dasharray="${dashFor(hi)}"/>`; |
| 199 | + svg += `<path d="${path}" data-metric="${metric}" fill="none" stroke="${color}" stroke-width="2" stroke-dasharray="${dashFor(hi)}"/>`; |
198 | 200 | } |
199 | 201 | for (const p of pts) { |
200 | | - svg += `<circle cx="${p.x.toFixed(1)}" cy="${p.y.toFixed(1)}" r="3.5" fill="${color}">` + |
| 202 | + svg += `<circle cx="${p.x.toFixed(1)}" cy="${p.y.toFixed(1)}" r="3.5" data-metric="${metric}" fill="${color}">` + |
201 | 203 | `<title>${metric}: ${p.e.metrics[metric]} ${unit}\n${p.e.date} · ${p.e.commit} · ${p.e.machine}</title></circle>`; |
202 | 204 | } |
203 | 205 | }); |
|
206 | 208 | document.getElementById(containerId).innerHTML = svg; |
207 | 209 |
|
208 | 210 | const legend = metrics.map((m, i) => |
209 | | - `<span><span class="swatch" style="background:${COLORS[i % COLORS.length]}"></span>${m}</span>`); |
| 211 | + `<span data-metric="${m}"><span class="swatch" style="background:${COLORS[i % COLORS.length]}"></span>${m}</span>`); |
210 | 212 | if (shownMachines.length > 1) { |
211 | 213 | legend.push(...shownMachines.map((m, i) => |
212 | 214 | `<span><span class="swatch" style="background:#999;${i ? "background:repeating-linear-gradient(90deg,#999 0 4px,transparent 4px 8px)" : ""}"></span>${m}</span>`)); |
213 | 215 | } |
214 | | - document.getElementById(legendId).innerHTML = legend.join(""); |
| 216 | + const legendEl = document.getElementById(legendId); |
| 217 | + legendEl.innerHTML = legend.join(""); |
| 218 | + |
| 219 | + // hovering a legend key dims every other series in this chart |
| 220 | + const setFocus = metric => { |
| 221 | + document.querySelectorAll(`#${containerId} [data-metric]`).forEach(el => { |
| 222 | + el.style.opacity = metric && el.getAttribute("data-metric") !== metric ? 0.08 : 1; |
| 223 | + }); |
| 224 | + }; |
| 225 | + legendEl.querySelectorAll("[data-metric]").forEach(item => { |
| 226 | + item.addEventListener("mouseenter", () => setFocus(item.getAttribute("data-metric"))); |
| 227 | + item.addEventListener("mouseleave", () => setFocus(null)); |
| 228 | + }); |
215 | 229 | } |
216 | 230 |
|
217 | 231 | function render() { |
|
0 commit comments