Weiter zum Inhalt
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Hell
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dunkel
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Visualisierung
  4. Dynamische HTML-Progress-Bar

NEWS

  • wichtiges UPDATE für controller 7.2.2 im stable
    HomoranH
    Homoran
    10
    1
    2.2k

  • Neues YouTube-Video: Visualisierung im Devices-Adapter
    BluefoxB
    Bluefox
    16
    1
    4.1k

  • Neuer ioBroker-Blog online: Monatsrückblick März/April 2026
    BluefoxB
    Bluefox
    8
    1
    3.6k

Dynamische HTML-Progress-Bar

Geplant Angeheftet Gesperrt Verschoben Visualisierung
vis
1 Beiträge 1 Kommentatoren 244 Aufrufe 4 Beobachtet
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • Ro75R Online
    Ro75R Online
    Ro75
    schrieb am zuletzt editiert von Ro75
    #1

    Dieses Skript bietet eine elegante Lösung, um ohne aufwendige Widget-Konfigurationen voll anpassbare Fortschrittsbalken (horizontal oder vertikal) direkt per JavaScript zu generieren. Ideal für Dashboards, bei denen Füllstände, Batteriestände oder Sensorwerte grafisch ansprechend visualisiert werden sollen.

    76c66a4b-b1a0-4cc0-8494-04784944a4f8-image.jpeg

    Hinweis: Dieses Skript wurde mit Unterstützung von KI entwickelt, um eine effiziente und saubere Code-Struktur für die dynamische HTML-Generierung sicherzustellen.

    Warum dieses Skript?
    In der Visualisierung (VIS) stößt man bei vielen gleichartigen Elementen oft an Grenzen. Anstatt für jedes Widget manuell Einstellungen vorzunehmen, generiert dieses Skript den HTML-Code "on-the-fly".

    Einheitliches Design:
    Alle Balken sind konsistent.

    Flexibel:
    Einfache Anpassung von Farben, Größen und Stilen über Parameter.

    Performance:
    Nutzt leichtgewichtiges Inline-HTML/CSS, daher sehr schnell in basic-html Widgets.

    Was ist nötig?
    Du benötigst die Instanz javascript.

    Datenpunkt:
    Erstelle einen Datenpunkt (Typ String) in 0_userdata.0, in dem das generierte HTML gespeichert wird.

    Widget:
    Erstelle in deiner VIS ein basic-html Widget und binde den Datenpunkt per Bindings ein: {0_userdata.0.dein.datenpunkt}.

    Die Parameter-Erklärung

    Parameter Typ Beschreibung
    orientation String "horizontal" oder "vertical"
    value Number Aktueller Wert in Prozent (0 - 100)
    progressColor String Farbe des Balkens (Hex, RGB oder RGBA)
    backgroundColor String Hintergrundfarbe (Hex, RGB, RGBA, "transparent")
    border Number Rahmenstärke in Pixeln
    borderColor String Rahmenfarbe (Hex, RGB oder RGBA)
    borderRadius Number Eckenabrundung in Pixeln
    labelFont String Schriftart (z.B. "Arial")
    labelSize String Schriftgröße (z.B. "20px") "0px" wenn das Label ausgeblendet werden soll
    labelColor String Textfarbe (Hex, RGB oder RGBA)
    labelshadow Boolean true für dezenten Text-Schatten
    labelsuffix String Anhang hinter dem Wert (z.B. "%")
    gradient Boolean true für automatischen Farbverlauf
    effect String "glanz" für Glas-Effekt oder "none"
    maxValue Number Standardwert = 100, kann aber auch jeder andere Wert sein

    Farbangaben & Transparenz
    Die Funktion ist für Standard-CSS-Farben ausgelegt. Du kannst für alle Farb-Parameter (progressColor, backgroundColor, borderColor, labelColor) die folgenden Formate verwenden:

    Hex-Werte: (z. B. "#2a2a2a"). Wichtig: Für den Parameter gradient = true solltest du bevorzugt Hex-Werte verwenden, da die interne Logik für Farbverläufe darauf optimiert ist.

    RGB / RGBA: Du kannst Farben als rgb(r, g, b) oder mit Transparenz als rgba(r, g, b, alpha) definieren.

    Beispiel: "rgba(0, 128, 0, 0.5)" für ein halbtransparentes Grün.

    "transparent": Verwende das Schlüsselwort "transparent", um den Hintergrund komplett auszublenden.

    Hier das Script:

    // === Dynamische HTML-Progress-Bar ===
     
    //Erst-Version 1.0.0 - 01.07.2026
    //Version 1.0.1 - 01.07.2026
    //Ersteller Ro75.
     
    //Voraussetzungen (Version 1.0.1 getestet mit)
    //NodeJS: 22.22.x
    //Javascript-Adapter: 9.0.18
    //Admin-Adapter: 7.8.23
    //js-controler: 7.2.2
    
    function buildProgressBar(orientation, value, progressColor, backgroundColor, border, borderColor, borderRadius, labelFont, labelSize, labelColor, labelshadow = false, labelsuffix, gradient, effect, maxValue = 100) {
        function adjustColor(col, amt) {
            if (col[0] === "#") {
                let hex = col.slice(1);
                if (hex.length === 3) {
                    hex = hex[0]+hex[0] + hex[1]+hex[1] + hex[2]+hex[2];
                }
                let num = parseInt(hex, 16);
                let r = (num >> 16) + amt;
                let g = ((num >> 8) & 0xFF) + amt;
                let b = (num & 0xFF) + amt;
                r = Math.max(0, Math.min(255, r));
                g = Math.max(0, Math.min(255, g));
                b = Math.max(0, Math.min(255, b));
                return "#" + ((r << 16) | (g << 8) | b).toString(16).padStart(6, "0");
            }
    
            if (col.startsWith("rgb")) {
                let nums = col.replace(/[^\d.,]/g, "").split(",");
                let r = parseInt(nums[0]) + amt;
                let g = parseInt(nums[1]) + amt;
                let b = parseInt(nums[2]) + amt;
                let a = nums.length === 4 ? parseFloat(nums[3]) : null;
    
                r = Math.max(0, Math.min(255, r));
                g = Math.max(0, Math.min(255, g));
                b = Math.max(0, Math.min(255, b));
    
                if (a !== null) {
                    return `rgba(${r},${g},${b},${a})`;
                } else {
                    return `rgb(${r},${g},${b})`;
                }
            }
            return col;
        }
    
        const percent = (maxValue === 0) ? 0 : (value / maxValue) * 100;
        let finalProgressColor = progressColor;
    
        if (gradient === true) {
            const dark = adjustColor(progressColor, -40);
            const light = adjustColor(progressColor, +60);
    
            if (orientation === "horizontal") {
                finalProgressColor = `linear-gradient(to right, ${dark} 0%, ${progressColor} 50%, ${light} 100%)`;
            } else {
                finalProgressColor = `linear-gradient(to top, ${dark} 0%, ${progressColor} 50%, ${light} 100%)`;
            }
        }
    
        let glanz = "";
        if (effect === "glanz") {
            if (orientation === "horizontal") {
                glanz = `<div style="position:absolute;left:0;top:0;width:100%;height:45%;background:rgba(255,255,255,0.35);"></div>`;
            } else {
                glanz = `<div style="position:absolute;left:0;top:0;width:45%;height:100%;background:rgba(255,255,255,0.35);"></div>`;
            }
        }
    
        let labelShadowStyle = "";
        if (labelshadow === true) {
            labelShadowStyle = "text-shadow:1px 1px 2px black;";
        }
    
        let finalLabelText = value + " " + labelsuffix;
    
        if (orientation === "horizontal") {
            return `
                <div style="width:100%;height:100%;background:${backgroundColor};border:${border}px solid ${borderColor};border-radius:${borderRadius}px;box-sizing:border-box;position:relative;overflow:hidden;">
                    <div style="width:${percent}%;height:100%;background:${finalProgressColor};position:relative;">
                        ${glanz}
                    </div>
                    <div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:100%;text-align:center;color:${labelColor};font-family:${labelFont};font-size:${labelSize};font-weight:bold;${labelShadowStyle}pointer-events:none;">
                        ${finalLabelText}
                    </div>
                </div>
            `;
        } else {
            return `
                <div style="width:100%;height:100%;background:${backgroundColor};border:${border}px solid ${borderColor};border-radius:${borderRadius}px;display:flex;align-items:flex-end;box-sizing:border-box;position:relative;overflow:hidden;">
                    <div style="width:100%;height:${percent}%;background:${finalProgressColor};position:relative;">
                        ${glanz}
                    </div>
                    <div style="position:absolute;top:50%;left:50%;transform:translate(-50%,-50%) rotate(-90deg);font-family:${labelFont};font-size:${labelSize};font-weight:bold;color:${labelColor};${labelShadowStyle}pointer-events:none;white-space:nowrap;">
                        ${finalLabelText}
                    </div>
                </div>
            `;
        }
    }
    

    Anwendung mit on()-Trigger (Automatische Aktualisierung):
    Anstatt den Wert manuell zu setzen, solltest du das Skript durch einen Trigger auslösen lassen. So aktualisiert sich deine ProgressBar automatisch, sobald sich der Wert deines Sensors ändert:

    // Beispiel: Überwache einen Datenpunkt (z.B. einen Füllstand)
    on({ id: 'alias.0.Geräte.Level', change: 'any' }, function (obj) {
        
        // Die ProgressBar wird bei jeder Änderung des Datenpunktes neu berechnet
        let barHTML = buildProgressBar(
            "horizontal", 
            obj.state.val,              // Der aktuelle Wert vom Sensor
            "#2a2a2a",                  // progressColor
            "transparent",              // backgroundColor
            2,                          // border
            "#cccccc",                  // borderColor
            5,                          // borderRadius
            "Arial",                    // labelFont
            "20px",                     // labelSize
            "#ffffff",                  // labelColor
            true,                       // labelshadow
            "%",                        // labelsuffix
            true,                       // gradient
            "none",                     // effect
            100                         // maxValue
        );
    
        // Das Ergebnis in den Ziel-Datenpunkt schreiben
        setState('0_userdata.0.meine_bar', barHTML);
    });
    

    Hinweis zu anderen Visualisierungen:
    Dieses Skript generiert sauberen HTML/CSS-Code. Dadurch sollte es nicht nur in der klassischen vis, sondern auch in anderen Visualisierungen innerhalb von ioBroker (wie vis-2, jarvis oder anderen Adaptern, die HTML-Widgets unterstützen) problemlos funktionieren.

    Solltest du das Skript in einem anderen Adapter einsetzen und Probleme bei der Darstellung haben, empfehle ich, kurz im jeweiligen Unterforum des Adapters nachzufragen – meist ist dort nur eine kleine Anpassung der CSS-Klassen oder des Container-Wrappers nötig.

    Viel Erfolg beim Einbinden in dein Dashboard. Wer mag, kann sich auch die SVG-Version ansehen.

    Ro75.

    EDIT: Version 1.0.1

    • maxValue kann nun definiert werden. Standard ist 100.

    SERVER = Beelink U59 16GB DDR4 RAM 512GB SSD, FB 7490, FritzDect 200+301+440, ConBee II, Zigbee Aqara Sensoren + NOUS A1Z, NOUS A1T, Philips Hue ** ioBroker, REDIS, influxdb2, Grafana, PiHole, Plex-Mediaserver, paperless-ngx (Docker), MariaDB + phpmyadmin *** VIS-Runtime = Intel NUC 8GB RAM 128GB SSD + 24" Touchscreen

    1 Antwort Letzte Antwort
    0

    Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.

    Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.

    Mit deinem Input könnte dieser Beitrag noch besser werden 💗

    Registrieren Anmelden
    Antworten
    • In einem neuen Thema antworten
    Anmelden zum Antworten
    • Älteste zuerst
    • Neuste zuerst
    • Meiste Stimmen


    Support us

    ioBroker
    Community Adapters
    Donate

    339

    Online

    33.0k

    Benutzer

    83.4k

    Themen

    1.3m

    Beiträge
    Community
    Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
    ioBroker Community 2014-2026
    logo
    • Anmelden

    • Du hast noch kein Konto? Registrieren

    • Anmelden oder registrieren, um zu suchen
    • Erster Beitrag
      Letzter Beitrag
    0
    • Home
    • Aktuell
    • Tags
    • Ungelesen 0
    • Kategorien
    • Unreplied
    • Beliebt
    • GitHub
    • Docu
    • Hilfe