NEWS
[Gelöst] Ist es möglich die Breite dynamisch anzupassen?
-
Hi,
ich möchte die Breite eines Elements in Abhängigkeit eines Temperaturwertes mit Hilfe von Javascript anpassen und weis jedoch nicht ob dies möglich ist. Auf die Idee kam ich nachdem ich folgendes Script gefunden habe:
createState('Farbe.Rollladen.PC', { def: '', type: 'string', name: 'Status-Farbe des Rollladen PC', desc: 'Status-Farbe des Rollladen PC abhängig vom Level' }); var idFarbe = 'javascript.0.Farbe.Rollladen.PC'; // auf richtige Instanz achten on("hm-rpc.0.NEQ1362981.1.LEVEL", function (data) { var level = data.state.val; if (level == 100) { setState(idFarbe, 'green'); } else if (level === 0){ setState(idFarbe, 'red'); } else{ setState(idFarbe, 'orange'); } });
Hier wird die Farbe in Abhängigkeit des Levels angepasst.
Da ich ein JavaScript Anfänger bin wollte ich fragen ob dann auch etwas in der Art möglich ist:
createState('Temperatur.Kueche.Fenster', { def: '', type: 'string', name: 'Breite des Elements', desc: 'Breite des Elements in Abhängigkeit der Temp' }); var idLaenge = 'javascript.0.Temperatur.Kueche.Fenster'; // auf richtige Instanz achten on("hm-rpc.0.MEQxxxxxxx.4.ACTUAL_TEMPERATURE", function (data) { var level = data.state.val; if (level < 10) { setState(idLaenge, '200px'); } else if (level === 0){ setState(idLaenge, '100px'); } });
Vielleicht kann hier jemand helfen bzw. Auskunft geben?
Danke
Peoples
-
Müsste eigentlich funktionieren.
Nur Dein Skript wird die Breite immer auf 200px setzen.
if (level < 10) { setState(idLaenge, '200px'); } else if (level === 0){ setState(idLaenge, '100px'); }
Wenn die Größe < 10 ist, dann 200px.
Das else danach wird nie ausgeführt, da ein Wert von 0 auch schon im ersten Fall greift (ist auch kleiner 10).
Werte über 10 werden gar nicht betrachtet.
Welche Werte gibt es denn bei Dir?
[EDIT]
Ich würde auch erst einmal einen Datenpunkt anlegen und dort manuell den Wert ändern und schauen, ob sich die Breite Deines Widgets im laufenden VIS ändert. Wenn Das generell funktioniert, dann würde ich mich ans Skript begeben.
-
Hi,
also es geht im Detail darum dass ich eine horizontale "Temperaturlinie" erstellen möchte. Das wollte ich erst durch ein Widget realisieren jedoch ohne Erfolg.
Näheres hier:
http://forum.iobroker.net/viewtopic.php?f=30&t=5782
Auf dem Weg nach einer Alternativen Lösung fand ich dann deinen Beitrag dessen Codeschnippsel ich oben ja schon gezeigt habe. Da kam mir die Idee ein Html Element mit einem Verlauf zu machen:
.temp_horizontal{ background: linear-gradient(to right, #1c871b 0px,#f9f927 122px,#f9f927 214px,#ff0000 336px); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ border: black solid 1px; border-radius:2px; }
Ohne eine Angabe der Breite, diese jedoch dann in Abhängigkeit der Temperatur zu setzen (bspw.: 2°C -> 10px; 4°C ->15px usw.) doch leider will das nicht wirklich funktionieren. Ich habe jetzt folgendes zusammen "geschrieben":
createState('Temperatur.Kueche.Fenster', { def: '', type: 'string', name: 'Breite des Elements', desc: 'Breite des Elements in Abhängigkeit der Temp' }); var idLaenge = 'javascript.0.Temperatur.Kueche.Fenster'; // auf richtige Instanz achten on("testbreite", function (data) { var level = data.state.val; if (level <= 0) { setState(idLaenge, '20px'); } else if ((level > 2) && (level <= 2 )){ setState(idLaenge, '40px'); } else if ((level > 4) && (level <= 6 )){ setState(idLaenge, '40px'); } else if ((level > 6) && (level <= 8 )){ setState(idLaenge, '40px'); } else if ((level > 8) && (level <= 10 )){ setState(idLaenge, '40px'); } });
Das Widget schaut so aus:
[{"tpl":"tplValueFloat","data":{"oid":"testbreite","visibility-cond":"==","visibility-val":1,"is_comma":"true","is_tdp":"false","factor":"1","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"visibility-groups-action":"hide"},"style":{"left":"979px","top":"272px","z-index":"20","color":"white","background-color":"{javascript.0.Farbe.Rollladen.PC}","border-width":"2px","border-style":"solid","height":"30px","width":"{javascript.0.Temperatur.Kueche.Fenster}"},"widgetSet":"basic"}]
Doch wie bereits erwähnt bin ich bei IoBroker blutigster Anfänger und wüsste auch nicht wo ich da den Fehler suchen sollte.
Gruß
Peoples
-
Ohne eine Angabe der Breite, diese jedoch dann in Abhängigkeit der Temperatur zu setzen (bspw.: 2°C -> 10px; 4°C ->15px usw.) doch leider will das nicht wirklich funktionieren. Ich habe jetzt folgendes zusammen "geschrieben":
createState('Temperatur.Kueche.Fenster', { def: '', type: 'string', name: 'Breite des Elements', desc: 'Breite des Elements in Abhängigkeit der Temp' }); var idLaenge = 'javascript.0.Temperatur.Kueche.Fenster'; // auf richtige Instanz achten on("testbreite", function (data) { var level = data.state.val; if (level <= 0) { setState(idLaenge, '20px'); } else if ((level > 2) && (level <= 2 )){ setState(idLaenge, '40px'); } else if ((level > 4) && (level <= 6 )){ setState(idLaenge, '40px'); } else if ((level > 6) && (level <= 8 )){ setState(idLaenge, '40px'); } else if ((level > 8) && (level <= 10 )){ setState(idLaenge, '40px'); } }); ```` `
Du bist auf einen guten Weg
coole Idee.
Ich habe Dein Widget und das dazugehörige Binding gerade getestet. Der Farbverlauf wird dargestellt und wenn man in den Datenpunkt die Breite reinschreibt verändert sich die Widgetbreite in VIS. Das klappt also grundsätzlich.:-)
Einzig Dein Skript verstehe ich nicht.
Welcher Datenpunkt soll das denn sein?
on("testbreite", function (data) {
Du solltest im Admin unter Objekte im Datenpunkt javascript.0.Temperatur.Kueche.Fenster zum Testen Deine gewünschte Breite reinschreiben 100px, 300px usw. Habe ich mit Deinem Widget vorhin gemacht. Funktioniert.
Nun musst Du Dein Skript anpassen auf den richtigen Datenpunkt der Temperatur.
Welcher ist denn das?
[EDIT]
-
Also CSS für den Farbverlauf: funktioniert
-
Widget: funktioniert
-
Das Binding mit der Breite aus einem Datenpunkt: funktioniert
Jetzt ist es nur noch Dein Skript mit der richtigen Subscription.
An Deinem on() musst Du arbeiten und an Deinem if else Baum
-
-
Doch wie bereits erwähnt bin ich bei IoBroker blutigster Anfänger und wüsste auch nicht wo ich da den Fehler suchen sollte. `
Das Widget und die CSS Anpassung sieht nicht nach einem Anfänger aus.
Probier mal (2. Zeile ID Deines Homematic Temperatur Datenpunkts eintragen):
var idLaenge = 'Temperatur.Kueche.Fenster'; var idTemp = "hm-rpc.0.MEQxxxxxxx.4.ACTUAL_TEMPERATURE"; var scala = 10; // Temperatur * scala = Pixelbreite var logOn = true; createState(idLaenge,"init", { name: 'Breite des Elements', desc: 'Breite des Elements in Abhängigkeit der Temp', type: 'string', unit: '', role: 'value' }); function celsiusToPixel(temp) { var pixel = Math.round(temp*scala).toString()+"px"; if(logOn) log("Temperatur: " + temp + " -> " + pixel); return pixel; } function main() { setState("javascript."+instance+"."+idLaenge,celsiusToPixel(getState(idTemp).val)); } on({id: idTemp ,change:'ne'}, function(obj) { if(logOn) log("neue Temperatur: " + obj.state.val); setState("javascript."+instance+"."+idLaenge,celsiusToPixel(obj.state.val)); }); //Skriptstart: einmal schreiben setTimeout(main, 500);
-
Hi,
Anfänger bezieht sich auf IoBroker und Javascript, in html und CSS konnte ich schon die ein oder andere Erfahrung sammeln
Ich habe es jetzt folgender Maßen im Test und anscheinend funktioniert das:
createState('Temperatur.Kueche.Fenster', { def: '', type: 'string', name: 'Breite des Elements', desc: 'Breite des Elements in Abhängigkeit der Temp' }); var idLaenge = 'javascript.0.Temperatur.Kueche.Fenster'; // auf richtige Instanz achten on("hm-rpc.0.NEQ1411563.4.ACTUAL_TEMPERATURE", function (data) { var level = data.state.val; if (level <= 1) setState(idLaenge, '0px'); if ((level > 2) && (level <= 3)) setState(idLaenge, '5px'); if ((level > 3) && (level <= 4)) setState(idLaenge, '10px'); if ((level > 4) && (level <= 5)) setState(idLaenge, '15px'); if ((level > 5) && (level <= 6)) setState(idLaenge, '20px'); if ((level > 6) && (level <= 7)) setState(idLaenge, '25px'); if ((level > 7) && (level <= 8)) setState(idLaenge, '30px'); if ((level > 8) && (level <= 9)) setState(idLaenge, '40px'); if ((level > 9) && (level <= 10)) setState(idLaenge, '50px'); if ((level > 10) && (level <= 11)) setState(idLaenge, '60px'); if ((level > 11) && (level <= 12)) setState(idLaenge, '70px'); if ((level > 12) && (level <= 13)) setState(idLaenge, '80px'); if ((level > 13) && (level <= 14)) setState(idLaenge, '90px'); if ((level > 14) && (level <= 15)) setState(idLaenge, '100px'); if ((level > 15) && (level <= 16)) setState(idLaenge, '110px'); if ((level > 16) && (level <= 17)) setState(idLaenge, '120px'); if ((level > 17) && (level <= 18)) setState(idLaenge, '130px'); if ((level > 18) && (level <= 19)) setState(idLaenge, '140px'); if ((level > 19) && (level <= 20)) setState(idLaenge, '150px'); if ((level > 20) && (level <= 21)) setState(idLaenge, '160px'); if ((level > 21) && (level <= 22)) setState(idLaenge, '170px'); if ((level > 22) && (level <= 23)) setState(idLaenge, '180px'); if ((level > 23) && (level <= 24)) setState(idLaenge, '190px'); if ((level > 24) && (level <= 25)) setState(idLaenge, '200px'); if ((level > 25) && (level <= 26)) setState(idLaenge, '210px'); if ((level > 26) && (level <= 27)) setState(idLaenge, '220px'); if ((level > 27) && (level <= 28)) setState(idLaenge, '230px'); if ((level > 28) && (level <= 29)) setState(idLaenge, '240px'); if ((level > 29) && (level <= 30)) setState(idLaenge, '250px'); if ((level > 30) && (level <= 31)) setState(idLaenge, '260px'); if ((level > 31) && (level <= 32)) setState(idLaenge, '270px'); if ((level > 32) && (level <= 33)) setState(idLaenge, '280px'); if ((level > 33) && (level <= 34)) setState(idLaenge, '290px'); if ((level > 34) && (level <= 35)) setState(idLaenge, '300px'); if ((level > 35) && (level <= 36)) setState(idLaenge, '310px'); if ((level > 36) && (level <= 37)) setState(idLaenge, '320px'); if ((level > 37) && (level <= 38)) setState(idLaenge, '325px'); if ((level > 38) && (level <= 39)) setState(idLaenge, '330px'); if ((level > 39) && (level <= 40)) setState(idLaenge, '335px'); if (level >= 40) setState(idLaenge, '340px'); });
Das Problem ist nämlich dass ich eine max. Breite von 340px habe bedingt durch das angestrebte Design.
Da stellt sich mir jedoch noch folgende Frage: Ist es möglich über die Auswahl der Objekt ID im Widget, diese an das Script mit weiter zu reichen?
So bräuchte man nicht für jedes Thermostat ein sep. Script oder?.
Deine Lösung ist natürlich viel professioneller, werde versuchen ob ich das irgendwie so anpassen kann dass es auf 340 Pixel auf geht.
Auf jeden Fall Vielen Dank !
Gruß
Peoples
-
Das Problem ist nämlich dass ich eine max. Breite von 340px habe bedingt durch das angestrebte Design. `
Wenn Du bei 40° Maximum erreichen willst, dann kannst Du die Variable Scale oben auf 8.5 setzen (340 / 40 = 8.5).
Und dann in der Funktion den Maxmimalwert auf 340px begrenzen.
var scala = 8.5; // Temperatur * scala = Pixelbreite var maxWidth = 340; // ... function celsiusToPixel(temp) { var pixelNum = = Math.round(temp*scala); if(pixelNum > maxWidth) pixelNum = maxWidth; var pixelStr = pixelNum.toString()+"px"; if(logOn) log("Temperatur: " + temp + " -> " + pixelStr); return pixelStr; }
[EDIT]
@peoples:Da stellt sich mir jedoch noch folgende Frage: Ist es möglich über die Auswahl der Objekt ID im Widget, diese an das Script mit weiter zu reichen?
So bräuchte man nicht für jedes Thermostat ein sep. Script oder?. `
Da kenne ich leider keine Möglichkeit.
Du kannst aber ein Skript schreiben, welches auf mehrere Thermostate reagiert und dann mehrere Datenpunkte ändert.
-
Hallo,
warum nutzt du nicht die binding-Funktion für die Breite des Balkens als Style-Angabe?
Hab es gerade getestet. Dein Skript abgewandelt (andere EIngabequelle)
createState('TestbreiteEingabe', 0, true, { def: 0, type: 'number', name: 'Breite des Elements', desc: 'Breite des Elements in Abhängigkeit der Temp' }); createState('Testbreite', 0, true, { def: 0, type: 'number', name: 'Breite des Elements', desc: 'Breite des Elements in Abhängigkeit der Temp' }); var idLaenge = 'javascript.2.Testbreite'; // auf richtige Instanz achten on("javascript.2.TestbreiteEingabe", function (data) { var level = data.state.val; var testbreite = 0; if (level > 1) { testbreite = 100/40 * level; if (testbreite > 100) testbreite = 100; } log(testbreite); setState(idLaenge, testbreite); });
Zum Testen gebe ich jetzt im Admin-Reiter Objekte die Zahlen einfach per Hand in TestbreiteEingabe ein. natürlich geht auch jede andere Quelle.
habe die Datenpunkte auf Typ Zahl geändert und nutze die Instanz javascript.2.
Jetzt VIS:
[{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":false,"g_css_shadow_padding":false,"g_css_border":false,"g_gestures":false,"g_signals":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"html":"{javascript.2.Testbreite}"},"style":{"left":"83px","top":"814px","z-index":"20","width":"491px","height":"42px"},"widgetSet":"basic"}]
Das ist ein HTML Widget, welches ein div-Container malt, dessen Breite über CSS-Anweisung festgelegt wird. Diese Anweisung wird als Binding eingefügt. Die Hintergrundfarbe ist noch als rot festgelegt, kann aber genauso als Binding dynamisch gesetzt werden.
{javascript.2.Testbreite}
Das Widget hat eine feste Breite (passend zu deinem Layout), der Container im Widget passt seine Breite dynamisch an.
Gruß
Pix
Hier noch ein Bild: Bindings lassen sich in allen Felder in VIS verwenden:
-
Ich versuche gerade noch die einzelnen Schritte zu erörtern bzw. zu verstehen da ich ja kein JavaScript - Profi bin.
Aber die Lösung ist genial, so kann ich die Breite zentral in CSS anpassen und bin trotzdem so flexiebel die Breite bei Bedarf mal schnell zu verändern.
TOP
Dank dir!
-
Hänge mich hier auch mal mit an, da ich nach der gleichen Lösung für meine Visualisierung gesucht hatte wie peoples.
Gestern Abend mal noch schnell die Lösung von pix ausprobiert und funktioniert perfekt. Einfach klasse was mit iobroker und vis relativ unkompliziert machbar ist.
-
Hi,
ergänzend zu der Javascript-Lösung hier die von mir mittlerweile genutze Umsetzung ohne Scripte direkt in Vis mit Binding.
Der Widgetexport (Hier muss das Thermostat noch angepasst werden):
! ````
[{"tpl":"tplHtml","data":{"g_fixed":false,"g_visibility":false,"g_css_font_text":false,"g_css_background":true,"g_css_shadow_padding":false,"g_css_border":true,"g_gestures":false,"g_signals":false,"visibility-cond":"==","visibility-val":1,"visibility-groups-action":"hide","refreshInterval":"0","signals-cond-0":"==","signals-val-0":true,"signals-icon-0":"/vis/signals/lowbattery.png","signals-icon-size-0":0,"signals-blink-0":false,"signals-horz-0":0,"signals-vert-0":0,"signals-hide-edit-0":false,"signals-cond-1":"==","signals-val-1":true,"signals-icon-1":"/vis/signals/lowbattery.png","signals-icon-size-1":0,"signals-blink-1":false,"signals-horz-1":0,"signals-vert-1":0,"signals-hide-edit-1":false,"signals-cond-2":"==","signals-val-2":true,"signals-icon-2":"/vis/signals/lowbattery.png","signals-icon-size-2":0,"signals-blink-2":false,"signals-horz-2":0,"signals-vert-2":0,"signals-hide-edit-2":false,"html":" 1 ? 100/40value:'';value > 100? "100" : 100/40value}%">","lc-type":"last-change","lc-is-interval":true,"lc-is-moment":false,"lc-format":"","lc-position-vert":"top","lc-position-horz":"right","lc-offset-vert":0,"lc-offset-horz":0,"lc-font-size":"12px","lc-font-family":"","lc-font-style":"","lc-bkg-color":"","lc-color":"","lc-border-width":"0","lc-border-style":"","lc-border-color":"","lc-border-radius":10,"lc-zindex":0},"style":{"left":"521px","top":"255px","z-index":"3","width":"340px","height":"10px","border-width":"1px","border-style":"solid","border-color":"black","border-radius":"2px","background-color":"#404040"},"widgetSet":"basic"}]Und hier der CSS-Auszug:
.temp_horizontal{
background: linear-gradient(to right, #0e16e4 0px,#6488a2 60px,#dfab0d 110px,#fdff00 240px,#f00000 310px); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */}