NEWS
SVG in Abhängigkeit von Datenpunkten animieren
-
Hallo liebe Freunde des automatisierten Heims,
ich komme in einer Sache einfach nicht weiter. Ich möchte meine Heizungsanlage als Schema im VIS visualisieren. Hierzu möchte ich SVGs einbinden und diese je nach Heizungszustand animieren. MarkusL hat das mal hier gepostet:
[https://forum.iobroker.net/topic/12723/einfach-mal-zeigen-will-teil-2/328]
Stefan-G hatte an späterer Stelle mir schon etwas Hilfestellung gegeben: https://forum.iobroker.net/topic/12723/einfach-mal-zeigen-will-teil-2/884](https://forum.iobroker.net/topic/12723/einfach-mal-zeigen-will-teil-2/884)
Lange hatte ich keine Zeit, um das Projekt weiterzuverfolgen. Aber jetzt beginnt die neue Heizperiode und der Wunsch des Fertigstellens wird wieder größer...
Nach vielen Stunden habe ich zwar eine Menge über HTML, CSS, JS und SVGs gelernt, aber noch nichts animiert bekommen. Das gepostete Widget im o.g. Link erzeugt beim Importieren leider eine Fehlermeldung.
Mir wäre schon einmal geholfen, wenn ich wüsste, wo der JS-Code von [https://forum.iobroker.net/topic/12723/einfach-mal-zeigen-will-teil-2/892] hin muss - in den allgemeinen HTML-Teil des Widgets, oder unter "Skripte" im Projekt?
Ich würde mich freuen, wenn mich jemand an die Hand nimmt. Viele Dinge kenne ich ja bereits, Binding und so sind mir klar und ich beiße mich gerne auch durch Neues durch.
Für Eure Hilfe und Hinweise jetzt schon mal ein herzliches Dankeschön
Viele Grüße,
Timo -
@Spampunk
Hallo Timo,
ja da hast du dir was vorgenommen
Wenn man mal das Grundkonzept verinnerlicht hat funktioniert es auch ganz gut. Wenn der Tag mal nicht nur 24h hätte...
Heizung1.mp4Bevor ich es nachher wieder vergesse: es funktioniert korrekt nur in der Runtime, nicht im Editor! Zumindest im FireFox muss ich ab und an die Seite mit F5 nochmals neu laden, da es bei den Animationen sonst zu "komischen" Fehlern kommt. Ich habe Stunden damit verbracht den Fehler zu finden warum die Pumpe nicht dreht. Die Leitungen waren korrekt gefärbt, die Flussanimation funktionierte, nur die Pumpe drehte nicht. Nach einem simplen Refresh ging es dann...
Ziel: eine drehende Pumpe, einfärben der Leitung nach Temperatur und Flussanimation wenn die Pumpe dreht
(ohne Animation/Video diesmal)
Benötigt
- einen Datenpunkt true/false ob die Pumpe läuft.
- einen Datenpunkt mit einer Temperatur
Da ich noch keine Sensoren an der Heizung habe musste bei mir mein Laptop herhalten (true/false = on-/offline) und die aktuelle Außentemperatur.
Man könnte nun mit einem Widget arbeiten. Ich habe es auf 2 aufgeteilt, da ich zum Einen auch die Temperatur des Sensors anzeigen möchte. Zum Anderen lässt sich so die Temperaturanzeige einfach besser platzieren.- Widget: Basic-Html
Dort unter Allgemein -HTML:
Kollektor: <span id="kollektor_temp">{javascript.0.Wetterstation.Aussentemperatur}</span> °C<br>
Ist ein simples Binding "{}" auf einen Datenpunkt. Wichtig, wie jetzt bei allen anderen auch, ist allerdings die "id" (muss einmalig sein). Wir merken uns mal kollektor_temp (das soll bspw. die Temperatur des Solarkollektors repräsentieren).
- Widget: Basic-Html
Dort unter Allgemein -HTML:
<script type="text/javascript"> var svgNS = "http://www.w3.org/2000/svg"; setTimeout(function () { let Zirku_pumpe = {radar2.0.Acer-Laptop}; // Auslesen der Temperatur und umrechnen über die Funktion unten in eine Farbe // 20 = blau; 90 = rot let leitungsfarbe = color(parseInt(document.getElementById("kollektor_temp").innerHTML)); // Einfärben der Leitung entsprechend ihrer Temperatur document.getElementById("leitung1").setAttribute("stroke", leitungsfarbe); // Hier jetzt die Auswertung, ob die Pumpe läuft. Wenn ja, dann wird sie gedreht und // die Flussanimation wird eingeblendet. if (Zirku_pumpe == true) { document.getElementById("flussanimation1").style.display = "block"; addRotateTransform('pumpe1',5 ,1); } else { document.getElementById("flussanimation1").style.display = "none"; addRotateTransform('pumpe1',0 ,1); } }, 1); function addRotateTransform(target_id, speed, direction) { var element_to_rotate = document.getElementById(target_id); var my_transform = document.createElementNS(svgNS, "animateTransform"); var bb = element_to_rotate.getBBox(); var cx = bb.x + bb.width/2; var cy = bb.y + bb.height/2; my_transform.setAttributeNS(null, "attributeName", "transform"); my_transform.setAttributeNS(null, "attributeType", "XML"); my_transform.setAttributeNS(null, "type", "rotate"); my_transform.setAttributeNS(null, "dur", speed + "s"); my_transform.setAttributeNS(null, "repeatCount", "indefinite"); my_transform.setAttributeNS(null, "from", "0 "+cx+" "+cy); my_transform.setAttributeNS(null, "to", 360*direction+" "+cx+" "+cy); element_to_rotate.appendChild(my_transform); my_transform.beginElement(); } function color(value) { var highColor = "#ff3030"; var lowColor = "#3030ff"; var highTemp = 90; var lowTemp = 20; var retValue = lowColor; if (value > lowTemp) { var lr = parseInt("0x"+lowColor.substring(1,3)); var lg = parseInt("0x"+lowColor.substring(3,5)); var lb = parseInt("0x"+lowColor.substring(5,7)); var hr = parseInt("0x"+highColor.substring(1,3)); var hg = parseInt("0x"+highColor.substring(3,5)); var hb = parseInt("0x"+highColor.substring(5,7)); var cr = parseInt(lr + (hr-lr)*(value-lowTemp)/(highTemp-lowTemp)).toString(16); var cg = parseInt(lg + (hg-lg)*(value-lowTemp)/(highTemp-lowTemp)).toString(16); var cb = parseInt(lb + (hb-lb)*(value-lowTemp)/(highTemp-lowTemp)).toString(16); cr = cr.length == 1 ? "0"+cr: cr; cg = cg.length == 1 ? "0"+cg: cg; cb = cb.length == 1 ? "0"+cb: cb; retValue = "#"+cr+cg+cb; } if (value > highTemp) { retValue = highColor; } return retValue; } </script> <svg> // Dies ist eine CSS-Definition. Sie führt später zum Fließen in der Leitung <style>.flow { animation: dash 30s linear; animation-iteration-count: infinite; } </style> // Dies ist eine Leitung. Die grüne Farbe ist quasi nur Kontrolle. Bei korrektem Code // wird die Leitung entsprechend der Temperatur koloriert. <path id="leitung1" fill="none" stroke="green" stroke-width="6" d="M0 15h100v10H0z"/> // Dies als Overlay. Die Grafik deutet einfach einen Fluss in der Leitung an. Es bietet sich // an, dies nach Bedarf ein oder auszublenden; dies erledigt der Code unten. <g id="flussanimation1" fill="none" class="flow" stroke="#fff" stroke-dasharray="4" stroke-width="4" opacity=".5"> <path d="M 5.058 20.093 L 108.785 19.427"/> </g> // Dies ist einfach die Darstellung einer Pumpe; die wird durch den Code unten nach Bedarf gedreht (animiert) oder nicht <g id="pumpe1" stroke="#000" stroke-linecap="round" stroke-linejoin="bevel"> <path fill="#fff" d="M72.2 19.756c0 6-5 11-11.2 11s-11-5-11-11c0-6.2 5-11.2 11-11.2s11.3 5 11.3 11.2z"/> <path stroke-width=".8" d="M66.5 10.156v19l-8.2-4.6-8.3-4.7 8.3-4.7z"/> </g> </svg>
Ui, schon eine andere Hausnummer
#5: wir definieren einen Namen für die Pumpe und ein Binding auf den true/false Datenpunkt ob die Pumpe läuft oder nicht (bei mir eben Laptop an oder aus )
#8 wir lesen die Temperatur aus (hier könnte man ohne das andere Widget auch direkt per Binding auslesen) und weisen ihm eine Bezeichnung zu (später natürlich Aussagefähiger wie "Vorlauf_Puffer"). Wir lesen es per "id" aus dem Dokument aus und erinnern uns an "kollektor_temp".
#11 wir färben die "leitung1" (wieder eine ID) ein. Diese befindet sich im SVG-Teil #84. Sollte natürlich eine bessere ID bekommen, denn wer weiß später noch, dass leitung23 Vorlauf vom Pfuffer zum Kessel war...
#15-#22 Pumpenanimation ein-/ausschalten. Ich wiederhole mich, aber "flussanimation1" und "pumpe1" sind natürlich wieder IDs (und findet man so auch wieder im SVG-Teil) und sollten mal wieder eine bessere Bezeichnung erhalten...An den beiden Funktionen gibt es eigentlich nichts zu ändern, außer ev. die Temperatur ab/bis wann koloriert wird und eben die Farbe.
-
@SBorg
Wow, super! Vielen Dank für Deine ausführliche Anleitung.Werde ich heute oder morgen Abend testen und dann Feedback geben!Ich habe Deine Anleitung jetzt kurz in der Mittagspause ausprobiert (War so neugierig...) und es funktioniert! Mann, bin ich happy
Jetzt weiß ich, was ich zu tun habe und kann mich endlich an die Arbeit machen.
Herzlichen Dank!
Viele Grüße,
Timo -
@Spampunk Wenn man es einmal verinnerlicht hat ist es gar nicht mehr so schwer. Man muss halt nur verstehen, dass die ganzen Zuweisungen immer per ID erfolgen. So kannst du jedes Element im SVG-Teil beeinflussen und wesentlich mehr erreichen als per Binding oder CSS. Ich färbe zB. auch meinen Zwischenpuffer vor der Therme je nach Wassertemperatur um.
Nur beim Füllstand für den Gastank hänge ich aktuell. Rechteckig kein Problem (sähe aber bei den Rundungen links und rechts des Tanks blöd aus), aber mit den Rundungen klappt es einfach (noch) nicht. ...und ich will den Tank so habenIch nutze es auch für meine Tonnen. Die werden automatisch je nach Art eingefärbt, die Resttage bis zur Entleerung ändern sich auch farblich...