NEWS
SVG in Abhängigkeit von Datenpunkten animieren
-
@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...
-
@sborg
Hi sBorg.
Kannst du bitte einmal dein Code in dem SVG shape teilen?Ich versuche eine Grafik zu erstellen, die den Wert (String) eines Objektes formatiert darstellt. Deine Resttage bis zur Leerung sollten mir da beim verstehen des Codes helfen.
Zur Sicherheit: nutzt du aus dem "Basic-Widgets" das "Boolesches SVG"?
Hier das an Code, was ich mir online zusammengesucht habe:
<!DOCTYPE html> <html> <body> <svg height="100" width="100" xmlns="http://www.w3.org/2000/svg"> <path id="lineAC" d="M 2 150 q 1 -190 180 0 " stroke="gray" stroke-width="2" fill="none"/> <text style="fill:black;font-size:16px;"> <textPath href="#lineAC" startOffset="80">Status</textPath> </text> </svg> </body> </html>
Wie man sich denken kann, soll da natürlich nichht dauerhaft "Status" stehen sondern hier der Text des Objekts angezeigt werden.
Und hier, wie es gerade aussieht:
Danke für die Hilfe ...
-
@sborg sagte in SVG in Abhängigkeit von Datenpunkten animieren:
Widget: Basic-Html
Dort unter Allgemein -HTML:Evtl. noch ein Hinweis zur Optimierung.
Wenn man Binding in ein HTML Widget einbaut, dann wird bei jeder Aktualisierung
der komplette Inhalt des Widgets aus der Seite entfernt und sogleich wieder hinzugefügt.
Das kann bei komplexen Änderungen uU zu einem Flackern der Grafik führen.Von daher wäre es sinnvoll entweder,
A)
das ganze HTML/SVG auf dem Server berechnen zu lassen und dann komplett per Binding
einzufügen.
B)
Javascript und HTNL/SVG in unterschiedliche widgets zu legen, so das immer nur das Javascript-Widget bei neuen werten per binding aktualisiert wird und von dort aus per DOM-Zugriff (so wie du es mit der Anpassung der CSS-Transform-Regel gemacht hast) auf das vorhandene HTML/SVG-Modell zugreifst.Aber wie gesagt nur, wenn dich das flackern nicht stört oder du es gar nicht wahrnimmst, weil es eh sehr schnell geht.
-
@a1uca2d sagte in SVG in Abhängigkeit von Datenpunkten animieren:
Die folgenden Teile am besten entfernen:
<-!DOCTYPE html> <html> <body>
</body> </html>
Die darf es in einem HTML-Dokument nur einmal geben. Moderne Browser kommen damit zwar zurecht, ist aber wieder eine evtl Fehlerquelle, die zu komischen Verhalten führt.
Das Doctype/html/body wird in vis ja bereits definiert. Du fügst eigentlich nur ein HTML-Fragment mit dem html widget hinzu. -
@oliverio
Danke dir für den Hinweis.Hast du vielleicht auch eine Idee für meine eigentliche Frage?
-
Eigentlich einfach
du packst deine svg-datei in ein html widget, also genau so kopieren wie du es siehst.
An der Stelle wo der Text steht packst du dein Datenpunkt im binding format rein (hier {0_userdata.0.test})
und dann änderst du den Text im Datenpunkt, der sich dann gleich auch in vis wiederspiegelt.
Da ist halt nix animiertes dran, da es einfach ein Text entlang einem Pfad dargestellt ist.<svg height="100" width="100" xmlns="http://www.w3.org/2000/svg"> <path id="lineAC" d="M 2 150 q 1 -190 180 0 " stroke="gray" stroke-width="2" fill="none"/> <text style="fill:black;font-size:16px;"> <textPath href="#lineAC" startOffset="80">{0_userdata.0.test}</textPath> </text> </svg>
wenn sich etwas bewegen soll, könnte man auch sowas machen
<svg width="800" height="200" xmlns="http://www.w3.org/2000/svg"> <!-- Definiere den Sinuspfad --> <path id="sinuskurve" d="M 0 100 Q 100 50 200 100 T 400 100 T 600 100 T 800 100" fill="transparent" stroke="lightgray" stroke-width="1"/> <!-- Text, der der Kurve folgt --> <text font-size="20" fill="blue"> <textPath href="#sinuskurve" startOffset="0%" id="text"> {0_userdata.0.testFolder.b1} </textPath> </text> <!-- Animierte Bewegung der Sinuskurve --> <animate xlink:href="#sinuskurve" attributeName="d" dur="4s" repeatCount="indefinite" values=" M 0 100 Q 100 50 200 100 T 400 100 T 600 100 T 800 100; M 0 100 Q 100 150 200 100 T 400 100 T 600 100 T 800 100; M 0 100 Q 100 50 200 100 T 400 100 T 600 100 T 800 100 " /> </svg>
das 2. beispiel habe ich auf die schnelle mit chatgpt erstellt.
aber dazu muss man sich ein wenig mit svg auseinandersetzen.
https://wiki.selfhtml.org/wiki/SVG -
@oliverio
Soweit so gut.
Das verstehe ich nun. Tatsächlich hat mir nun auch ChatGPT deutlich weitergeholfen. Das Thema Animation hat mich angefixt.Nun wäre mein nächster Punkt: wie bekomme ich die Animation an und aus!? Ich habe hier mit ChatGPT versucht mir zu helfen... Wie man sich denken kann, es hat bei meiner fehlenden Kompetenz nicht funktioniert.
Hier einmal wie mein Code für das SVG Objekt jetzt aussieht:
<!DOCTYPE html> <html lang="de"> <head> <meta charset="UTF-8"> <title>SVG Text Animation</title> </head> <body> <svg width="120" height="120" xmlns="http://www.w3.org/2000/svg"> <defs> <path id="circlePath" d="M 60, 60 m -42, 0 a 42,42 0 1,1 84,0 a 42,42 0 1,1 -84,0"/> </defs> <text font-size="14" fill="black"> <textPath id="textPath" href="#circlePath"> {javascript.0.Beschattung.Jalousie_Kind1_Li_Status} </textPath> <animateTransform id="animation" attributeName="transform" attributeType="XML" type="rotate" from="0 60 60" to="360 60 60" dur="10s" repeatCount="indefinite" /> </text> </svg> <script type="text/javascript"> on({ id: 'javascript.0.Beschattung.Jalousie_Kind1_Li_Status', change: "any" }, async (obj) => { var value = obj.state.val; const animation = document.getElementById('animation'); const textPath = document.getElementById('textPath'); if (value == "running") { animation.setAttribute('begin', 'indefinite'); textPath.setAttribute('startOffset', '0'); } else { animation.setAttribute('begin', '0s'); textPath.setAttribute('startOffset', '0%'); } } </script> </body> </html>
Wie bekomme ich das Ding zum laufen?
Jemand eine Idee? -
@a1uca2d said in SVG in Abhängigkeit von Datenpunkten animieren:
ich glaube du vermischt da etwas.
- der on befehl ist ein befehl, der nur in der script instanz auf dem server gültig ist. im html widget oder scripttab von vis gibt es den nicht dafür gibt es dort das binding.
da erledigt aber vis vollkommen automatisch alle aktualisierung. - wenn du nur das svg in ein html widget einträgst, dann dreht sich der text doch schon alleine. was möchtest du darüber hinaus noch animieren?
- der befehl document.getElementById dagegen funktioniert nur im browser und nicht auf dem server (im javascript adapter). wie man eine animation startet oder beendet musste ich selbst nachschauen -> https://developer.mozilla.org/de/docs/Web/API/SVGAnimationElementhttps://developer.mozilla.org/de/docs/Web/API/SVGAnimationElement
das sind die Befehle animation.beginElement() und animation.endElement() auf Basis deines Codes, da die Animation in der Variable animation referenziert ist.
Aber wie gesagt, die Animation läuft ja schon.
und nochmal, entferne die html und body tags, die brauchst du nicht in vis
- der on befehl ist ein befehl, der nur in der script instanz auf dem server gültig ist. im html widget oder scripttab von vis gibt es den nicht dafür gibt es dort das binding.
-
Du hast Recht. Nachdem ich den Post abgesetzt hatte habe ich auch darüber noch mal nachgedacht
Zu deiner Frage 2: ich möchte eigentlich, dass der Text sich nicht dauerhaft dreht. Folgende Regel: Wenn die Jalousie sich bewegt (Text: running), dann soll der Text sich drehen. Wenn die Jalousie steht, soll auch der Text stehen (Text: waiting)
So sieht meine letzte Version des Scripts aus:
<svg width="120" height="120" xmlns="http://www.w3.org/2000/svg"> <defs> <path id="circlePath" d="M 60, 60 m -42, 0 a 42,42 0 1,1 84,0 a 42,42 0 1,1 -84,0"/> </defs> <text font-size="14" fill="black"> <textPath id="textPath" href="#circlePath"> {javascript.0.Beschattung.Jalousie_Kind1_Li_Status} </textPath> <animateTransform id="animation" attributeName="transform" attributeType="XML" type="rotate" from="0 60 60" to="360 60 60" dur="10s" repeatCount="indefinite" /> </text> <circle r="30" cx="60" cy="60" stroke="" stroke-width="3" fill="grey" opacity="0.6" /> </svg> <script type="text/javascript"> schedule("*/5 * * * * *", async function () { var value = {javascript.0.Beschattung.Jalousie_Kind1_Li_Status}; const animation = document.getElementById('animation'); const textPath = document.getElementById('textPath'); if (value == "running") { textPath.setAttribute('startOffset', '0'); } else { animation.setAttribute('begin', '0s'); textPath.setAttribute('startOffset', '0%'); } } </script>
Wie leider zu erwarten funktioniert das auch nicht.
Eine weitere Beobachtung von mir: beim Ändern des Textes dauert es fast 10Sek bevor der Text wieder anfängt sich zu drehen. Was mache ich da denn falsch? Meine Erwartung wäre gewesen, dass der Text sich einfach beim drehen ändern aber keine Auswirkung auf die Drehung hat.
-
Für meine neue Frage habe ich durch ausprobieren eine Lösung gefunden.
<animateTransform id="animation" attributeName="transform" attributeType="XML" type="rotate" from="0 60 60" to="360 60 60" begin="0.1s" dur="8s" repeatCount="indefinite" />
Ausschlaggebend ist hier das Attribut "begin" es darf nur nicht bei "0s" stehen.