Metainformationen zur Seite
  •  

Unterschiede

Hier werden die Unterschiede zwischen zwei Versionen angezeigt.

Link zu dieser Vergleichsansicht

iobroker_vis_in_homarr_skalierung_zentrierung_und_hidpi [10.10.2026] – angelegt koljaiobroker_vis_in_homarr_skalierung_zentrierung_und_hidpi [10.10.2026] (aktuell) – gelöscht kolja
Zeile 1: Zeile 1:
-====== ioBroker VIS in Homarr – Skalierung, Zentrierung und HiDPI ====== 
- 
-===== Zweck ===== 
-Die VIS-Ansicht **trash** wird als iFrame in Homarr dargestellt. Beim Verändern der Homarr-Kachel werden alle Widgets gemeinsam proportional skaliert und horizontal/vertikal zentriert. Canvas-Gauges werden mit höherer interner Auflösung gezeichnet, damit sie auf Monitoren mit unterschiedlicher Pixeldichte scharf bleiben. 
- 
-^ Einstellung ^ Wert / Funktion ^ 
-| VIS-Ansicht | ''trash'' | 
-| VIS-Auflösung | 400 × 480 px (wird aus VIS gelesen) | 
-| Hintergrund | ''#25262b'' | 
-| Max. HiDPI-Faktor | ''4'' | 
-| Startbedingung | Nur im iFrame, nicht im VIS-Editor | 
-| Anpassungen bei neuen Widgets | Keine JavaScript-Widget-IDs notwendig | 
- 
-===== Einrichtung ===== 
-  - Im VIS-Editor das entsprechende Projekt öffnen. 
-  - Unter **Projekt / Skripte (JavaScript)** den bisherigen Skalierungs-Code vollständig durch den folgenden JavaScript-Code ersetzen. Nicht doppelt einfügen. 
-  - Unter **Projekt-CSS** den bisherigen CSS-Code für dieses Homarr-Layout durch den nachfolgenden CSS-Code ersetzen. 
-  - Änderungen speichern und Homarr vollständig neu laden. 
-  - Homarr-Kachel kleiner/größer ziehen und Darstellung prüfen. 
- 
-===== JavaScript – automatische Skalierung, Zentrierung und scharfe Gauges ===== 
-<code javascript> 
-/** 
- * ioBroker VIS (Ansicht "trash") in Homarr 
- * -------------------------------------- 
- * - Gesamte VIS proportional an die iFrame-Größe anpassen. 
- * - Inhalt horizontal und vertikal zentrieren. 
- * - Alle Canvas-Gauges automatisch in höherer Auflösung zeichnen. 
- * - Keine festen Widget-IDs; neu hinzugefügte Gauges werden mit erfasst. 
- * 
- * Einbau: VIS-Editor -> Projekt -> Skripte / JavaScript. 
- * Die Funktion läuft bewusst nur in einem iFrame, nicht im VIS-Editor. 
- */ 
-(function () { 
-    // Nicht in einem eigenständigen Browserfenster oder im VIS-Editor ausführen. 
-    if (window.self === window.top) return; 
-    if (window.vis && window.vis.editMode) return; 
- 
-    // Verhindert eine doppelte Registrierung der Beobachter bei erneutem Laden. 
-    if (window.trashAutoScaleActive) return; 
-    window.trashAutoScaleActive = true; 
- 
-    // Name der VIS-Ansicht. Nur bei Umbenennung der Ansicht ändern. 
-    const VIEW_NAME = "trash"; 
- 
-    // Ersatzwerte, falls die VIS-Einstellungen noch nicht verfügbar sind. 
-    // Aktuelle Ansichtsgröße: 400 x 480 Pixel (wird normalerweise automatisch gelesen). 
-    const FALLBACK_WIDTH = 400; 
-    const FALLBACK_HEIGHT = 480; 
- 
-    // HiDPI: höhere Werte = schärfer, aber größerer Grafik-/Speicherbedarf. 
-    const MAX_PIXEL_RATIO = 4; 
- 
-    let updatePending = false;      // Begrenzt Layout-Berechnungen auf einen pro Frame. 
-    let canvasClass = null;         // Canvas-Klasse der geladenen Gauge-Bibliothek. 
-    let currentPixelRatio = 1;      // Tatsächlich verwendeter HiDPI-Faktor. 
-    let redrawTimer = null;         // Entprellt das Neuzeichnen bei Größenänderungen. 
- 
-    /** 
-     * Erhöht die interne Zeichenauflösung der Canvas-Gauges. 
-     * Die sichtbaren Abmessungen der Widgets bleiben dabei unverändert. 
-     * 
-     * Wichtig: Die Bibliothek stellt "SmartCanvas" im Browser nicht zwingend 
-     * als window.SmartCanvas bereit. Deshalb ermitteln wir die Klasse über 
-     * das bereits erzeugte Gauge-Objekt eines beliebigen Canvas-Widgets. 
-     * Danach gilt der neue Faktor automatisch für alle Gauges dieser Klasse. 
-     */ 
-    function updateCanvasResolution(scale) { 
-        let Canvas = canvasClass; 
- 
-        // Bibliotheksklasse einmalig über ein vorhandenes Gauge finden. 
-        if (!Canvas) { 
-            const view = document.getElementById("visview_" + VIEW_NAME); 
-            if (!view || !window.jQuery) return; 
- 
-            const canvases = view.querySelectorAll("canvas.vis-canvas-gauges"); 
- 
-            for (const element of canvases) { 
-                const widget = element.closest(".vis-widget"); 
-                if (!widget) continue; 
- 
-                const gauge = window.jQuery(widget).data("gauge"); 
- 
-                if ( 
-                    gauge && gauge.canvas && 
-                    typeof gauge.canvas.constructor.redraw === "function" 
-                ) { 
-                    Canvas = gauge.canvas.constructor; 
-                    break; 
-                } 
-            } 
-        } 
- 
-        // Gauges noch nicht geladen: Beim nächsten Layout-Update erneut prüfen. 
-        if (!Canvas) return; 
- 
-        // Bildschirm-Pixeldichte + Vergrößerung der gesamten VIS berücksichtigen. 
-        // Untergrenze 3x; Obergrenze 4x gegen unnötigen Ressourcenverbrauch. 
-        const dpr = window.devicePixelRatio || 1; 
-        const desired = Math.min( 
-            MAX_PIXEL_RATIO, 
-            Math.max(3, dpr * Math.max(1, scale) * 1.25) 
-        ); 
-        const nextRatio = Math.ceil(desired * 4) / 4; 
- 
-        let installedNow = false; 
- 
-        // Den zentralen PixelRatio-Getter der tatsächlichen Klasse einmal ersetzen. 
-        if (canvasClass !== Canvas) { 
-            const descriptor = Object.getOwnPropertyDescriptor(Canvas, "pixelRatio"); 
- 
-            if (!descriptor || !descriptor.configurable) { 
-                console.warn("Canvas-Gauges: Pixeldichte nicht anpassbar"); 
-                return; 
-            } 
- 
-            try { 
-                Object.defineProperty(Canvas, "pixelRatio", { 
-                    configurable: true, 
-                    get: function () { 
-                        return currentPixelRatio; 
-                    } 
-                }); 
-                canvasClass = Canvas; 
-                installedNow = true; 
-            } catch (error) { 
-                console.warn("Canvas-Gauges: HiDPI-Aktivierung fehlgeschlagen", error); 
-                return; 
-            } 
-        } 
- 
-        // Ohne Änderung der benötigten Pixeldichte nicht erneut zeichnen. 
-        if ( 
-            !installedNow && 
-            Math.abs(nextRatio - currentPixelRatio) < 0.01 
-        ) { 
-            return; 
-        } 
- 
-        currentPixelRatio = nextRatio; 
- 
-        // Kurze Verzögerung vermeidet viele Redraws beim Ziehen der Homarr-Kachel. 
-        clearTimeout(redrawTimer); 
-        redrawTimer = setTimeout(function () { 
-            try { 
-                canvasClass.redraw(); 
-                console.info("VIS Canvas-Gauges HiDPI:", currentPixelRatio + "x"); 
-            } catch (error) { 
-                console.warn("Canvas-Gauges: Neuzeichnen fehlgeschlagen", error); 
-            } 
-        }, 220); 
-    } 
- 
-    /** 
-     * Passt die ganze VIS proportional in die aktuelle iFrame-Fläche ein. 
-     * Die Ansicht behält ihr Seitenverhältnis und wird in beiden Achsen zentriert. 
-     */ 
-    function scaleView() { 
-        updatePending = false; 
- 
-        const container = document.getElementById("vis_container"); 
-        const view = document.getElementById("visview_" + VIEW_NAME); 
-        if (!container || !view) return; 
- 
-        // Größe des tatsächlich verfügbaren VIS-Containers (Homarr-iFrame). 
-        const width = container.clientWidth; 
-        const height = container.clientHeight; 
-        if (width <= 0 || height <= 0) return; 
- 
-        // Originalgröße direkt aus den VIS-Ansichtseinstellungen beziehen. 
-        // Bei einer späteren Änderung der VIS-Auflösung keine Code-Anpassung nötig. 
-        const settings = 
-            window.vis && window.vis.views && 
-            window.vis.views[VIEW_NAME] && 
-            window.vis.views[VIEW_NAME].settings; 
- 
-        const baseWidth = 
-            parseInt(settings && settings.sizex, 10) || FALLBACK_WIDTH; 
-        const baseHeight = 
-            parseInt(settings && settings.sizey, 10) || FALLBACK_HEIGHT; 
- 
-        // "contain": gesamte VIS sichtbar halten, niemals verzerren. 
-        const scale = Math.min(width / baseWidth, height / baseHeight); 
- 
-        // Freie Fläche links/rechts und oben/unten gleichmäßig verteilen. 
-        const offsetX = (width - baseWidth * scale) / 2; 
-        const offsetY = (height - baseHeight * scale) / 2; 
- 
-        // Ausgangsposition und Ausgangsabmessungen explizit setzen. 
-        view.style.position = "absolute"; 
-        view.style.left = "0px"; 
-        view.style.top = "0px"; 
-        view.style.width = baseWidth + "px"; 
-        view.style.height = baseHeight + "px"; 
- 
-        // VIS hat standardmäßig min-width/min-height: 100 %. 
-        // Das würde unsere Größenberechnung beim Verkleinern verfälschen. 
-        view.style.minWidth = "0px"; 
-        view.style.minHeight = "0px"; 
- 
-        // Zentrierung und Skalierung in einer Transformation kombinieren. 
-        view.style.transformOrigin = "top left"; 
-        view.style.transform = 
-            `translate(${offsetX}px, ${offsetY}px) scale(${scale})`; 
- 
-        // Den Canvas-Gauges ausreichend interne Bildpunkte geben. 
-        updateCanvasResolution(scale); 
-    } 
- 
-    // Mehrere unmittelbar aufeinanderfolgende Änderungen zusammenfassen. 
-    function requestUpdate() { 
-        if (updatePending) return; 
-        updatePending = true; 
-        requestAnimationFrame(scaleView); 
-    } 
- 
-    function initialize() { 
-        const container = document.getElementById("vis_container"); 
-        if (!container) return; 
- 
-        // Homarr-iFrame/Browserfenster wird größer oder kleiner. 
-        window.addEventListener("resize", requestUpdate); 
- 
-        // VIS-Container ändert sich, auch ohne klassisches window.resize. 
-        if (typeof ResizeObserver !== "undefined") { 
-            new ResizeObserver(requestUpdate).observe(container); 
-        } 
- 
-        // Widgets werden beim VIS-Start ggf. verzögert eingefügt. 
-        // So finden wir die Gauge-Bibliothek auch nach dem ersten Rendern. 
-        new MutationObserver(requestUpdate).observe(container, { 
-            childList: true, 
-            subtree: true 
-        }); 
- 
-        requestUpdate(); 
-    } 
- 
-    // Erst starten, wenn der HTML-Dokumentbaum verfügbar ist. 
-    if (document.readyState === "loading") { 
-        document.addEventListener("DOMContentLoaded", initialize, { once: true }); 
-    } else { 
-        initialize(); 
-    } 
-})(); 
-</code> 
- 
-===== Projekt-CSS – Hintergrund und Trashschedule ===== 
-<code css> 
-/* ============================================================ 
-   ioBroker VIS "trash" in Homarr – Projekt-CSS 
-   ============================================================ */ 
- 
-/* 1. Seitenränder entfernen: Der iFrame-Inhalt beginnt ohne Abstand. */ 
-html, 
-body, 
-.mainWrapper { 
-    margin: 0 !important; 
-    padding: 0 !important; 
-} 
- 
-/* 2. Überlauf ausblenden: Keine Scrollbalken im Homarr-iFrame. 
-      Achtung: html/body wirken auf ALLE Ansichten dieses VIS-Projekts. */ 
-html, 
-body, 
-.mainWrapper, 
-#vis_container, 
-.no-scrollbars { 
-    overflow: hidden !important; 
-} 
- 
-/* 3. Einheitlicher Hintergrund auf allen Ebenen. 
-      Verhindert weiße Streifen bei wechselnder iFrame-Größe. 
-      Achtung: html/body und #vis_container wirken projektweit. */ 
-html, 
-body, 
-.mainWrapper, 
-#vis_container, 
-#visview_trash { 
-    background-color: #25262b !important; 
-} 
- 
-/* 4. Trashschedule: Mülltonnen trotz schmalem Rahmen nebeneinander. 
-      Selektor über Widget-Klasse statt ID: auch für weitere 
-      Trashschedule-Widgets innerhalb der Ansicht "trash". */ 
-#visview_trash .trashschedule-widget .trashtypes { 
-    white-space: nowrap !important; 
-    width: max-content !important; 
-    transform-origin: top left !important; 
-} 
- 
-/* 5. Weniger Abstand: Tonnen kompakter nebeneinander anordnen. */ 
-#visview_trash .trashschedule-widget .trashtype { 
-    margin-left: 5px !important; 
-    margin-top: 0 !important; 
-} 
- 
-/* Kein zusätzliches CSS für Canvas-Gauges notwendig: 
-   Die höhere Zeichenauflösung regelt das JavaScript. */ 
-</code> 
- 
-===== Funktionsprinzip ===== 
-  * **Skalierung:** Die VIS passt mit einem einheitlichen Faktor vollständig in den iFrame (Seitenverhältnis bleibt erhalten). 
-  * **Zentrierung:** Nicht genutzte Breite und Höhe werden auf beide Seiten verteilt. 
-  * **HiDPI:** Die Canvas-Gauges zeichnen intern mit höherer Pixeldichte; sichtbare Widgetmaße bleiben gleich. 
-  * **Neue Widgets:** Die VIS-Gesamtskalierung gilt automatisch. Weitere Widgets aus derselben Canvas-Gauges-Bibliothek profitieren ebenfalls von der HiDPI-Einstellung. 
-  * **Mülltonnen:** CSS verhindert Zeilenumbrüche und reduziert die Zwischenräume. 
-  * **Hintergrund:** Alle relevanten VIS-Ebenen verwenden ''#25262b'', damit keine weißen Flächen erscheinen. 
- 
-===== Anpassungen und Hinweise ===== 
-  * ''VIEW_NAME'': Nur ändern, wenn die Ansicht ''trash'' umbenannt wird. 
-  * ''FALLBACK_WIDTH'' / ''FALLBACK_HEIGHT'': Ersatzwerte, falls die gespeicherte VIS-Auflösung nicht rechtzeitig verfügbar ist. Im Normalfall wird die Ansichtsgröße automatisch ausgelesen. 
-  * ''MAX_PIXEL_RATIO'': Obergrenze für die Canvas-Zeichenauflösung. Größere Werte benötigen mehr Grafikleistung und Speicher. 
-  * **Projektweit:** CSS auf ''html'', ''body'' und ''#vis_container'' beeinflusst auch andere Ansichten desselben VIS-Projekts. Bei scrollbaren Ansichten gegebenenfalls getrennt konfigurieren. 
-  * **Grenze:** Die HiDPI-Funktion ist auf die verwendete ''vis-canvas-gauges''-Bibliothek abgestimmt; bei einem größeren Bibliotheksupdate kann eine Überprüfung erforderlich werden. Andere Canvas-Widgets werden nicht automatisch in HiDPI gezeichnet. 
-  * **Fehlersuche:** Im Browser (Entwicklerkonsole des VIS-iFrames) erscheint bei erfolgreichem HiDPI-Neuzeichnen z. B. ''VIS Canvas-Gauges HiDPI: 3x''. Falls keine Meldung erscheint, prüfen, ob Gauges bereits geladen sind und ob die Browserkonsole Fehler zeigt. 
- 
-===== Wartung ===== 
-Vor größeren Änderungen VIS-Projekt exportieren/sichern. Beim Hinzufügen normaler Widgets ist keine Anpassung des JavaScripts erforderlich; nur bei einer geänderten Ansichtsnamen oder abweichendem Widget-Typ die Konfiguration prüfen.