diff options
| author | Paul Buetow <paul@buetow.org> | 2026-02-24 20:18:53 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-02-24 20:18:53 +0200 |
| commit | 81735bb46a75dce67a06e383f0703871e23b29d4 (patch) | |
| tree | d8c002b5f9908774f73637f0ce27de2c4e0fdfbe /internal/flamegraph/svgwriter_jscode.go | |
| parent | b8e683e41364fcfd9edda05c4e35a8af3a21835d (diff) | |
flamegraph: add native svg renderer and embedded js
Diffstat (limited to 'internal/flamegraph/svgwriter_jscode.go')
| -rw-r--r-- | internal/flamegraph/svgwriter_jscode.go | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/internal/flamegraph/svgwriter_jscode.go b/internal/flamegraph/svgwriter_jscode.go new file mode 100644 index 0000000..52f8818 --- /dev/null +++ b/internal/flamegraph/svgwriter_jscode.go @@ -0,0 +1,77 @@ +//go:build !js + +package flamegraph + +const flamegraphJS = ` +const fg = { + frames: [], + info: null, + matchColor: "rgb(220, 30, 70)", +}; + +function fgInit() { + fg.frames = Array.from(document.querySelectorAll("g.frame")); + fg.info = document.getElementById("fg-info"); + fg.frames.forEach((frame) => { + frame.addEventListener("click", (ev) => fgZoom(ev.currentTarget)); + frame.addEventListener("mouseenter", (ev) => fgHover(ev.currentTarget)); + }); + document.addEventListener("dblclick", () => fgResetZoom()); +} + +function fgHover(frame) { + if (!fg.info) return; + const title = frame.querySelector("title"); + fg.info.textContent = title ? title.textContent : ""; +} + +function fgZoom(frame) { + const x = Number(frame.dataset.x || "0"); + const w = Number(frame.dataset.w || "0"); + if (w <= 0) return; + const end = x + w; + fg.frames.forEach((other) => { + const ox = Number(other.dataset.x || "0"); + const ow = Number(other.dataset.w || "0"); + const sameBand = Number(other.dataset.depth || "0") >= Number(frame.dataset.depth || "0"); + if (sameBand && ox >= x && ox + ow <= end) { + other.style.display = ""; + } else { + other.style.display = "none"; + } + }); +} + +function fgResetZoom() { + fg.frames.forEach((frame) => { + frame.style.display = ""; + }); +} + +function fgSearch() { + const needle = prompt("Search frames (substring):", ""); + if (needle === null) return; + const q = needle.trim().toLowerCase(); + fg.frames.forEach((frame) => { + const rect = frame.querySelector("rect"); + const base = frame.dataset.baseFill || ""; + const name = (frame.dataset.name || "").toLowerCase(); + if (!rect) return; + if (q !== "" && name.includes(q)) { + rect.style.fill = fg.matchColor; + } else { + rect.style.fill = base; + } + }); +} + +function fgResetSearch() { + fg.frames.forEach((frame) => { + const rect = frame.querySelector("rect"); + if (!rect) return; + rect.style.fill = frame.dataset.baseFill || ""; + }); +} + +window.addEventListener("DOMContentLoaded", fgInit); +` |
