Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
2.3 kB · 63 lines
JavaScript
at dev
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364// The one deliberate JS island (docs/06): pan/zoom for the SVG sky viewport.// No framework, ~100 lines. Everything functions without it; reduced-motion// preference disables transitions (handled in CSS).(function () { var wrap = document.getElementById("skyviewport"); if (!wrap) return; var svg = wrap.querySelector("svg"); if (!svg) return;
var vb = (svg.getAttribute("viewBox") || "0 0 1000 1000").split(/\s+/).map(Number); var view = { x: vb[0], y: vb[1], w: vb[2], h: vb[3] }; var home = { x: vb[0], y: vb[1], w: vb[2], h: vb[3] };
function apply() { svg.setAttribute("viewBox", view.x + " " + view.y + " " + view.w + " " + view.h); }
function clientToSvg(cx, cy) { var r = svg.getBoundingClientRect(); return { x: view.x + ((cx - r.left) / r.width) * view.w, y: view.y + ((cy - r.top) / r.height) * view.h, }; }
svg.addEventListener("wheel", function (e) { e.preventDefault(); var factor = e.deltaY > 0 ? 1.15 : 1 / 1.15; var p = clientToSvg(e.clientX, e.clientY); var nw = Math.min(Math.max(view.w * factor, home.w / 16), home.w * 2); var nh = (nw / view.w) * view.h; view.x = p.x - ((p.x - view.x) / view.w) * nw; view.y = p.y - ((p.y - view.y) / view.h) * nh; view.w = nw; view.h = nh; apply(); }, { passive: false });
var dragging = null; svg.addEventListener("pointerdown", function (e) { dragging = { cx: e.clientX, cy: e.clientY, x: view.x, y: view.y }; svg.setPointerCapture(e.pointerId); }); svg.addEventListener("pointermove", function (e) { if (!dragging) return; var r = svg.getBoundingClientRect(); view.x = dragging.x - ((e.clientX - dragging.cx) / r.width) * view.w; view.y = dragging.y - ((e.clientY - dragging.cy) / r.height) * view.h; apply(); }); svg.addEventListener("pointerup", function () { dragging = null; }); svg.addEventListener("dblclick", function () { view = { x: home.x, y: home.y, w: home.w, h: home.h }; apply(); });
// Keyboard focus order follows centrality: stars are emitted in layout order, // most central first; make them tabbable. var stars = svg.querySelectorAll(".star, .dark-star"); stars.forEach(function (g, i) { g.setAttribute("tabindex", i + 1); });})();