From 640cb95c27d9c9d9c38923c712150d12955261c0 Mon Sep 17 00:00:00 2001 From: mhoennig Date: Wed, 22 Jul 2026 21:16:03 +0200 Subject: [PATCH] frontend: Zoom-Controls mit Auto-Collapse-Funktion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Zoom-Controls collapse automatisch nach 3 Sekunden Inaktivität - Toggle-Button mit Lupe+Plus-Symbol zum Expandieren der Controls - Position weiter nach rechts-unten verschoben (6px) - Event-Delegation für zuverlässige Click-Erfassung - Lazy-Loading der DOM-Elemente für robuste Initialisierung Co-Authored-By: Claude Haiku 4.5 --- frontend/index.html | 11 ++++++++--- frontend/src/app.js | 18 ++++++++++++++++++ frontend/src/style.css | 6 +++++- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index 8a169bb..0d51073 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -140,9 +140,14 @@
    - - - + +
    + + + +
    diff --git a/frontend/src/app.js b/frontend/src/app.js index f1cc4d0..dc2ba7e 100644 --- a/frontend/src/app.js +++ b/frontend/src/app.js @@ -443,22 +443,40 @@ gutter.addEventListener('dblclick', () => { /* CSS-`zoom` skaliert die Layout-Box, dadurch greifen die Scrollbalken des Diagramm-Containers korrekt (anders als transform: scale). */ const ZMIN = 0.3, ZMAX = 3, ZSTEP = 0.1; +const ZOOM_COLLAPSE_DELAY = 3000; /* 3 Sekunden */ let zoom = 1; +let zoomCollapseTimeout; + +function resetZoomCollapseTimeout(){ + const zoomctl = document.querySelector('.zoomctl'); + if(!zoomctl) return; + clearTimeout(zoomCollapseTimeout); + zoomctl.classList.remove('collapsed'); + zoomCollapseTimeout = setTimeout(() => { + zoomctl.classList.add('collapsed'); + }, ZOOM_COLLAPSE_DELAY); +} + function applyZoom(){ zoom = Math.min(ZMAX, Math.max(ZMIN, Math.round(zoom * 100) / 100)); out.style.zoom = zoom; document.getElementById('zoomReset').textContent = Math.round(zoom * 100) + ' %'; + resetZoomCollapseTimeout(); saveUI(); } document.getElementById('zoomIn').addEventListener('click', () => { zoom += ZSTEP; applyZoom(); }); document.getElementById('zoomOut').addEventListener('click', () => { zoom -= ZSTEP; applyZoom(); }); document.getElementById('zoomReset').addEventListener('click', () => { zoom = 1; applyZoom(); }); +document.querySelector('.zoomctl').addEventListener('click', (e) => { + if(e.target.closest('#zoomToggle')) resetZoomCollapseTimeout(); +}); diagramEl.addEventListener('wheel', e => { if(!(e.ctrlKey || e.metaKey)) return; /* Strg/Cmd + Mausrad zoomt */ e.preventDefault(); zoom += (e.deltaY < 0 ? ZSTEP : -ZSTEP); applyZoom(); }, {passive:false}); +resetZoomCollapseTimeout(); /* Initialer Timeout beim Laden */ const showc = document.getElementById('showc'); function discardedShown(){ return showc.getAttribute('aria-pressed') === 'true'; } diff --git a/frontend/src/style.css b/frontend/src/style.css index 36e7fcc..b012676 100644 --- a/frontend/src/style.css +++ b/frontend/src/style.css @@ -343,7 +343,7 @@ /* Zoom-Steuerung: schwebt unten rechts über dem Diagramm. */ .zoomctl{ - position:absolute;right:14px;bottom:14px;z-index:5; + position:absolute;right:6px;bottom:6px;z-index:5; display:inline-flex;align-items:center;gap:2px;padding:2px; background:var(--card);border:1px solid rgba(36,52,71,.18); border-radius:8px;box-shadow:0 1px 4px rgba(36,52,71,.14); @@ -355,6 +355,10 @@ } #zoomReset{min-width:48px;font-size:.72rem} .zoomctl button:hover{background:var(--paper);color:var(--or)} + .zoomToggle{display:none;padding:6px} + .zoomToggle svg{width:20px;height:20px} + .zoomctl.collapsed .zoomToggle{display:block} + .zoomctl.collapsed .zoomcontrols{display:none} .panel.collapsed .zoomctl{display:none} /* ---------- Baum ---------- */