docs: click-to-zoom lightbox for diagrams (scroll-zoom + drag-pan)
Graphviz renders SVG as <object>, which swallows clicks and can't be lightboxed. Vendored, dependency-free zoom.js converts each graphviz <object> to a clickable <img> (crisp vector) and adds a fullscreen overlay: click to open, scroll to zoom toward the cursor, drag to pan, Esc / dbl-click / background-click to close. Works for any img.zoomable, so future charts get it free. Degrades gracefully (no JS -> inline image still renders). Wired via html_css_files / html_js_files.
This commit is contained in:
parent
5dd9c18f79
commit
2a37c6ec51
3 changed files with 160 additions and 0 deletions
43
docs/_source/_static/zoom.css
Normal file
43
docs/_source/_static/zoom.css
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/* Click-to-zoom for diagrams (graphviz SVG + any img.zoomable).
|
||||
Vendored, dependency-free. See zoom.js. */
|
||||
|
||||
.graphviz img,
|
||||
img.zoomable {
|
||||
cursor: zoom-in;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
#arb-zoom-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 100000;
|
||||
background: rgba(10, 12, 16, 0.92);
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
cursor: grab;
|
||||
}
|
||||
#arb-zoom-overlay.open { display: block; }
|
||||
#arb-zoom-overlay.grabbing { cursor: grabbing; }
|
||||
|
||||
#arb-zoom-overlay img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
max-width: none;
|
||||
transform-origin: 0 0;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
#arb-zoom-hint {
|
||||
position: fixed;
|
||||
top: 10px;
|
||||
right: 16px;
|
||||
z-index: 100001;
|
||||
display: none;
|
||||
color: #fff;
|
||||
font: 13px/1.4 system-ui, sans-serif;
|
||||
opacity: 0.75;
|
||||
pointer-events: none;
|
||||
}
|
||||
#arb-zoom-overlay.open ~ #arb-zoom-hint { display: block; }
|
||||
112
docs/_source/_static/zoom.js
Normal file
112
docs/_source/_static/zoom.js
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/* Click-to-zoom lightbox for docs diagrams. Dependency-free.
|
||||
*
|
||||
* Sphinx renders graphviz SVG as <object>, which swallows clicks and
|
||||
* can't be lightboxed. We replace each with an <img> (crisp vector,
|
||||
* clickable), then a click opens a fullscreen overlay with
|
||||
* scroll-to-zoom + drag-to-pan so dense diagrams can be read in detail.
|
||||
* Esc / double-click / background-click closes. Degrades gracefully:
|
||||
* if JS is off, the inline image still renders. */
|
||||
(function () {
|
||||
function ready(fn) {
|
||||
if (document.readyState !== "loading") fn();
|
||||
else document.addEventListener("DOMContentLoaded", fn);
|
||||
}
|
||||
|
||||
ready(function () {
|
||||
// 1. graphviz <object> SVG -> clickable <img>
|
||||
document
|
||||
.querySelectorAll('.graphviz object[type="image/svg+xml"]')
|
||||
.forEach(function (obj) {
|
||||
var img = document.createElement("img");
|
||||
img.src = obj.getAttribute("data");
|
||||
img.className = "zoomable";
|
||||
img.alt = "diagram — click to zoom";
|
||||
obj.parentNode.replaceChild(img, obj);
|
||||
});
|
||||
|
||||
// 2. overlay scaffold
|
||||
var ov = document.createElement("div");
|
||||
ov.id = "arb-zoom-overlay";
|
||||
var big = document.createElement("img");
|
||||
ov.appendChild(big);
|
||||
var hint = document.createElement("div");
|
||||
hint.id = "arb-zoom-hint";
|
||||
hint.textContent = "scroll = zoom · drag = pan · Esc / dbl-click = close";
|
||||
document.body.appendChild(ov);
|
||||
document.body.appendChild(hint);
|
||||
|
||||
var scale = 1, tx = 0, ty = 0;
|
||||
var dragging = false, moved = false, sx = 0, sy = 0;
|
||||
|
||||
function apply() {
|
||||
big.style.transform =
|
||||
"translate(" + tx + "px," + ty + "px) scale(" + scale + ")";
|
||||
}
|
||||
function open(src) {
|
||||
ov.classList.add("open");
|
||||
big.onload = function () {
|
||||
var s =
|
||||
Math.min(
|
||||
window.innerWidth / big.naturalWidth,
|
||||
window.innerHeight / big.naturalHeight
|
||||
) * 0.95;
|
||||
scale = s > 0 ? s : 1;
|
||||
tx = (window.innerWidth - big.naturalWidth * scale) / 2;
|
||||
ty = (window.innerHeight - big.naturalHeight * scale) / 2;
|
||||
apply();
|
||||
};
|
||||
big.src = src;
|
||||
}
|
||||
function close() {
|
||||
ov.classList.remove("open");
|
||||
big.src = "";
|
||||
}
|
||||
|
||||
document.body.addEventListener("click", function (e) {
|
||||
var t = e.target;
|
||||
if (t && t.classList && t.classList.contains("zoomable")) open(t.src);
|
||||
});
|
||||
|
||||
ov.addEventListener(
|
||||
"wheel",
|
||||
function (e) {
|
||||
e.preventDefault();
|
||||
var f = e.deltaY < 0 ? 1.15 : 1 / 1.15;
|
||||
// zoom toward the cursor
|
||||
tx = e.clientX - (e.clientX - tx) * f;
|
||||
ty = e.clientY - (e.clientY - ty) * f;
|
||||
scale *= f;
|
||||
apply();
|
||||
},
|
||||
{ passive: false }
|
||||
);
|
||||
|
||||
ov.addEventListener("mousedown", function (e) {
|
||||
dragging = true;
|
||||
moved = false;
|
||||
sx = e.clientX - tx;
|
||||
sy = e.clientY - ty;
|
||||
ov.classList.add("grabbing");
|
||||
});
|
||||
window.addEventListener("mousemove", function (e) {
|
||||
if (!dragging) return;
|
||||
moved = true;
|
||||
tx = e.clientX - sx;
|
||||
ty = e.clientY - sy;
|
||||
apply();
|
||||
});
|
||||
window.addEventListener("mouseup", function () {
|
||||
dragging = false;
|
||||
ov.classList.remove("grabbing");
|
||||
});
|
||||
|
||||
// background click (no drag) closes; dbl-click + Esc close
|
||||
ov.addEventListener("click", function (e) {
|
||||
if (e.target === ov && !moved) close();
|
||||
});
|
||||
ov.addEventListener("dblclick", close);
|
||||
document.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Escape") close();
|
||||
});
|
||||
});
|
||||
})();
|
||||
|
|
@ -43,6 +43,11 @@ html_theme = "sphinx_book_theme"
|
|||
html_static_path = ["_static"]
|
||||
html_title = "Arborist API Reference"
|
||||
|
||||
# Click-to-zoom lightbox for diagrams (graphviz SVG + img.zoomable).
|
||||
# Vendored, dependency-free — see _static/zoom.{css,js}.
|
||||
html_css_files = ["zoom.css"]
|
||||
html_js_files = ["zoom.js"]
|
||||
|
||||
# Standard sphinx-book-theme layout: full project TOC on the left,
|
||||
# 'On this page' (current page sections) on the right. show_toc_level=3
|
||||
# expands the right TOC down to subsections.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue