Einfache Animation (Energy-Flow) - wie in Winforms

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von Fakiz.

    Einfache Animation (Energy-Flow) - wie in Winforms

    Hallo Leute,

    ich habe eine Windows Anwendung für Photovoltaik-Wechselrichter und Smarthome.
    Dort habe ich eine Energy-Flow Grafik integriert.
    (Bild mit den bunten Kacheln). Die Energiefluss-Linien sind fixe starre Linien mit Pfeilen.

    Nun habe ich in den vergangenen Tagen eine Web-Version davon erstellt (CSS/HTML/Javascript/PHP).
    Dort wollte ich das ganze identisch umsetzen. Ich habe das zuerst mit <canvas> und Zeichnen per Javascript gemacht.
    Das sah dann 1:1 so aus wie in der VB.NET Anwendung.

    Nun habe ich mich aber auch etwas mit SVG gespielt und habe das sogar animiert hinbekommen (bopv.app/Canvas_vs_SVG.mp4).
    Im Video sieht man oben das Ergebnis mit <canvas> und unten das mit SVG.

    Nun habe ich Blut geleckt und möchte so eine Animation natürlich auch in meiner VB.NET Anwendung hinbekommen.
    Die "faule" Variante wäre, einfach ein Webbrowser-Control zu nehmen und dort das selbe animierte SVG anzuzeigen.
    Das ist mir dann aber doch "zu billig".

    Daher wollte ich Euch fragen, ob Ihr Ideen habt, wie ich so eine Energiefluss-Animation in WinForms hinbekomme, ohne dass das ganze ruckelt, wenn man die Maus bewegt oder im Hintergrund etwas berechnet wird.

    LG Roland
    Bilder
    • 18032024195001.jpg

      832,44 kB, 2.102×1.198, 65 mal angesehen
    • 18032024195229.jpg

      324,26 kB, 1.274×712, 68 mal angesehen
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Lass das bleiben mit Forms. Lerne WPF oder nutze in Forms eine Bibliothek die Hardwarebeschleunigt rendert.(SDL2, SDL3, OpenGl, DirectX, ...) Gibt auch Bibliotheken womit man solche Technologien in NET nutzen kann. Mit SDL und DirectX kannste anstatt ein WindowHandle zum rendern auch ein Controlhandle nehmen, so das nicht auf ein ganzes Fenster sondern nur auf dem einen Control gemalt wird, wird vermutlich auch mit OpenGL so sein, hab da aber keine Ahnung von. Man kann zwar auch mit Forms recht flott rendern, aber da kommt man sehr schnell an Grenzen. In WPF hat man "Storyboards" zur Verfügung damit kann man Controls animieren, baut man sich ein eigenes, kann man noch mehr machen.


    Erstelle deine Videos doch bitte Web-Konform wenn du sie hier verlinkst, kann es im Firefox nicht abspielen, musste extra runterladen und dem VLC zu futtern geben.

    PS:
    Auch ein Path oder eine Geometry kann man animieren in WPF:(wobei dort ein Button einen Pfad folgt, kannste auch auch mit Rectangles machen oder sonstwelchen feinen Grafiken.
    learn.microsoft.com/en-us/dotn…w=netframeworkdesktop-4.8

    Hab gerade gesehen, das ist wieder ein Code den ich nicht mag als Beispiel. Falls du den evtl. probierst und nicht zum laufen bekommst und WPF deshalb direkt verteufelst, im Anhang eine lauffähige Projektmappe.
    Dateien
    • Anim.zip

      (4,74 kB, 1.070 mal heruntergeladen, zuletzt: )
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „DTF“ ()

    DTF schrieb:

    Lass das bleiben mit Forms. ...die Hardwarebeschleunigt rendert ... DirectX
    Sagen wir mal so, es ist durchaus mit "ein paar Zeilen Code, ohne zusätzliche DLLs oder Referenzen" möglich, mit WIC und Direct2D, eine SVG in WinForms zu rendern und sogar zu erstellen. Ob man darüber auch animierte SVGs gerendert bekommt, kann ich im Moment nicht sagen. Du hast aber vollen Zugriff auf die XML der SVG und kannst so also neue Elemente hinzufügen/löschen/ändern usw. Die Frage ist nur, ob sich der Aufwand lohnt denn ganz ohne ist das nicht.
    Mfg -Franky-
    Ja WIC ist sehr mächtig, hab WIC mit DirectX genutzt um Texturen zu laden, aber ein einfaches Thema ist das nicht unbedingt. Falls dive26 bei Forms bleiben will, könnte er auch ein ElementHost in Forms nutzen. So müsste dive26 nur ein Control in WPF machen.
    learn.microsoft.com/en-us/dotn…p-8.0&redirectedfrom=MSDN

    Dann hätte er zumindest das Control Hardwarebeschleunigt. Ich denke neben seiner Idee einfach ein WebbrowserControl zu nutzen, ist ein ElementHost auch eine recht einfache, aber durchaus akzeptable Lösung. Da würde ich sogar denken das er das leicht umsetzen kann. Mit HTML, CSS und JS kommt er ja scheinbar klar und ich finde WPF ist leichter zu lernen, denn mit CSS da gibt es oft mal überraschungen die einen das ganze Design zerreißen können und man erstmal die Ursache finden muss, was je nach Skills nicht unbedingt trivial ist.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    Jupp, viele Wege führen zum Ziel. Ob das alte Webbrowser-Control dafür noch geeignet ist, kann ich nicht sagen und ich glaub dive26 wollte nicht unbeding WebView2 verwenden/ausrollen/installieren/verteilen. Das WinRT Webbrowser-Control wäre eine alternative dazu und bis .NET 4.8.xx auch einfach per Referenz auf die Windows.winmd einfach zuverwenden auch wenn dieser noch die alte Edge-Renderengine verwendet und erst ab Win10 zur Verfügung steht.
    Mfg -Franky-
    Danke Euch.
    Aber WPF kommt für mich aktuell so überhaupt nicht in Frage.

    Werde mir das mit WIC und SVG mal näher ansehen - womöglich ist das die Lösung. Kann mir da ja ein UserControl dafür bauen, dem ich einfach die SVG-Infos übergeben muss. Stell mir das jetzt einfach vor - wird aber wohl schwieriger werden - wenn schon Ihr Profis da "erzittert" ;) .
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Naja meine alten Knochen klappern da nicht mehr, hab das ja alles schon hinter mir und bin damit vertaut. Schade das WPF für dich nicht in Frage kommt, ist eine tolle Sache wenn man damit umgehen kann. Zudem ist es einfacher wirklich hübsche UIs mit leichtigkeit zu machen, versuch mal in Forms so eine Ansicht zu machen, die auch noch eine gute Performance liefert. Ist ein ListView mit UserControls. Selbst mit 1000+ Items komm ich nicht über 5% CPU, auch auf Systemen ohne dedizierte GPU rennt das sehr gut. Hätte sogar noch optimierungsmöglickeiten, aber das brauch ich nicht mal machen. Diese UserControls wollte ich noch aufklappbar machen, um mehr Albumdetails anzuzeigen, so eine UI in Forms wäre X-mal aufwändiger und nicht so performant.


    Da WPF keine Option für dich ist, ist der Webbrowser die einfachere Variante.
    Bilder
    • Unbenannt.jpg

      316,42 kB, 1.884×633, 63 mal angesehen
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „DTF“ ()

    @DTF

    Bin gerade dabei das mit einem Webbrowser Control zu testen.
    Leider kann aber das alte "Internet Explorer" Webbrowser Control keine Styles in der SVG Datei darstellen.
    Die Brauche ich aber für die Animation.

    WebView als Control ist mir aber zu aufgebläht und hat zu viele Abhängigkeiten.
    Am liebsten wäre mir eine einzige .dll im Anwendungsordner und ein einfaches Webbrowser-Control, welches auch die Animierte CSV interpretieren kann.

    Hier ein Beispiel CSV:

    HTML-Quellcode

    1. <?xml version='1.0' encoding='utf-8'?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' xmlns:xml='http://www.w3.org/XML/1998/namespace'><style>.animleft {stroke-dasharray: 4; animation: dashdraw 12s linear infinite;}@keyframes dashdraw {to {stroke-dashoffset: 200;}}.animright {stroke-dasharray: 4; animation: dashdraw 12s linear infinite reverse;}@keyframes dashdraw {to {stroke-dashoffset: 200;}}text {font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;font-size: 14px;font-weight: 400;fill:white;}line { stroke-linejoin:round;fill:none;stroke-width:3;}</style><line class='animright' x1='10' y1='20' x2='300' y2='20' stroke='mediumseagreen' /><line class='animleft' x1='10' y1='30' x2='300' y2='30' stroke='orangered' /></svg>
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Also nur 1 DLL, das wird glaube ich schwierig. Webbrowser sind so aufwändig, da ist es sinnvoller alles in verschiedenen DLLs aufzuteilen. Schon allein weil man viel kompilierzeit einspart, nur weil man z.B. einen JS Interpeter updated, will man ja nicht die ganze RenderingEngine wieder gleich mit kompilieren wenn es nicht sein muss.

    Also ich hab mal deine SVG mit dem CEF-Sharp browser probiert, hab einfach das Demo-Projekt hier:(Kannste für dein Projekt als Nuget Packet laden)
    github.com/cefsharp/CefSharp.MinimalExample

    Dein SVG wird animiert gezeigt. Aber wenn du den verwendest, hast du auch einen aufgeblähten Ausgabeordner.

    Du kannst aber auch versuchen ob es mit Forms ausreichend flüssig läuft, brauchst ja nur ein CustomControl machen und rectangle malen.
    So z.B.

    VB.NET-Quellcode

    1. Imports System.Drawing.Drawing2D
    2. Public Class Flowthing
    3. Inherits Control
    4. Public Sub New()
    5. SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer, True)
    6. Width = 1000
    7. Height = 20
    8. End Sub
    9. Private Rect As New Rectangle(0, 0, 20, 20)
    10. Private StartOffset As Integer = 0
    11. Private WithEvents Ticker As New Timer With {.Enabled = True, .Interval = 10}
    12. Private Sub Ticker_Tick(sender As Object, e As EventArgs) Handles Ticker.Tick
    13. StartOffset += 1
    14. If StartOffset > 25 Then
    15. StartOffset = 0
    16. End If
    17. Invalidate()
    18. End Sub
    19. Protected Overrides Sub OnPaint(e As PaintEventArgs)
    20. MyBase.OnPaint(e)
    21. e.Graphics.TranslateTransform(StartOffset, 0, MatrixOrder.Append)
    22. For i As Integer = 0 To Width Step 25
    23. e.Graphics.TranslateTransform(25, 0, MatrixOrder.Append)
    24. e.Graphics.FillRectangle(Brushes.Blue, Rect)
    25. Next
    26. End Sub
    27. End Class


    Kann man drüber streiten ob das gut ist, Forms-Timer in Kombination mit malen war ich nie ein Fan von.
    Bilder
    • Unbenannt.jpg

      108,63 kB, 255×1.098, 52 mal angesehen
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    @DTF

    Mit Forms/Timer/e.Graphics habe ich es bereits versucht.
    Das ruckelt und flimmert mir etwas zu viel. Ist nicht wirklich brauchbar.

    @-Franky-
    Ja, das Thema SVG hatten wir schon mal.
    Wie schon damals, habe ich auch kein Problem das SVG zu erstellen und auch das Rendering gelingt mit "vielen" Komponenten recht einfach.
    Aber eben immer nur als Standbilder.
    Aber hier geht es ja nicht nur einfach um ein starres SVG-Bild, sondern um eine Animation im SVG.
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    Wie schon damals, habe ich auch kein Problem das SVG zu erstellen und auch das Rendering gelingt mit "vielen" Komponenten recht einfach.
    Aber eben immer nur als Standbilder.
    Aber hier geht es ja nicht nur einfach um ein starres SVG-Bild, sondern um eine Animation im SVG.

    Das meinete ich als ich schrieb, da müsste man wohl direkt auf das XML der SVG zugreifen. ID2D1DeviceContext5::CreateSvgDocument -> ID2D1SvgDocument::xxx und weiter ID2D1SvgDocument::GetRoot -> ID2D1SvgElement::xxx Hier müsstest wohl die Position der Dots (Linie) darüber manipulieren und erneut rendern. Hab ich bisher selbst noch nicht gemacht.
    Mfg -Franky-
    @-Franky-
    ​darüber manipulieren und erneut rendern. Hab ich bisher selbst noch nicht gemacht.

    Auch wenn man das so machen würde, dann müsste man die damit erzeugte Grafik ja wieder in der Form anzeigen - sehr oft hintereinander.
    Dann kann ich das ja genausogut mit e.graphics machen. Was ich aber schon probiert habe - und das ergibt keine flüssige Animation, sondern ein unschönes Flackern (trotzt doublebuffering).
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    und das ergibt keine flüssige Animation, sondern ein unschönes Flackern
    Hier müsste man dann unter Umständen einen DirectX-SwapChain einsetzen. Das bläht den Code noch weiter auf, flackert dann aber nicht mehr. Wie geschrieben, der Aufwand das selbst zu programmieren ist sehr hoch.
    Mfg -Franky-
    War beim Control/Form denn DoubleBuffered == True? Wenn nicht, kann das eine Ursache sein warum es so geflackert hat.Evtl. hast du auch eine zu große Fläche geupdated, man kann auch einfach gezielt nur bestimmte Bereiche neu malen. Die überladungen von Control.Invalidate() kennste bestimmt schon oder?
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D
    @DTF
    ​War beim Control/Form denn DoubleBuffered == True? Wenn nicht, kann das eine Ursache sein warum es so geflackert hat.

    Ja, das habe ich sowieso aktiviert. Sonst würde der generelle Aufbau zu sehr flackern.
    Je öfter man aber das Paint-Event aufruft, desto mehr sieht man das Flackern.
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Ich hoffe du hast ein Control gerendert und nicht Form.Invalidate() genommen. Denn dann werden auch alle Controls auf dem Form neu gemalt, das kostet dann Zeit und Leistung.

    PS: @dive26
    Bei mir flackert nichts, nur perfekt ist das auch nicht.
    streamable.com/hras7w
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „DTF“ ()

    @DTF
    Bei mir flackert nichts, nur perfekt ist das auch nicht.


    Bei einer Linie flackert bei mir auch nichts.
    Aber wenn die Grafik aus 8 Linien und zusätzlichen Grafiken besteht und die Form sonst auch was anderes zu tun hat - dann wird es flackerig ;)
    Bilder
    • 19032024150106.jpg

      91,16 kB, 729×306, 42 mal angesehen
    • 19032024150145.jpg

      104,83 kB, 686×297, 47 mal angesehen
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Naja Forms ist halt nicht gut für sowas, da sind wir uns ja einig. Aber wenns geflackert hat, hast du irgendwo was nicht richtig. Das einzige was bei mir passiert ist, je mehr von diesen Controls auf dem Form sind, umso langsamer wird das. Ich könnte da nun noch was weis ich nicht noch alles aufs Form werfen, wird nur langsamer, bis mit dem Rendern nicht mehr hinterher gekommen werden kann. Keine Ahnung wie du deine UI geamcht hast. Aber wenn das alles einzelne Controls sind, solltest du eigendlich keine Probleme haben.
    https://streamable.com/c1vy4g



    Solltest du die Form so in einem durchgang malen, und auch immer updaten dann nimm einen Wrapper für SDL und male Hardwarebeschleunigt das Form.
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „DTF“ ()

    Ohne zu wissen was du bereits versucht hast wäre hier mal mein Ansatz.

    Spoiler anzeigen

    C#-Quellcode

    1. using System;
    2. using System.Drawing;
    3. using System.Windows.Forms;
    4. namespace AnimationTest
    5. {
    6. internal class MarqueePanel : Panel
    7. {
    8. private Bitmap backgroundImage;
    9. private float backgroundImageX;
    10. private readonly Timer timer;
    11. private readonly float step = -100;
    12. public MarqueePanel()
    13. {
    14. SetBackgroundImage();
    15. timer = new Timer();
    16. timer.Interval = 10;
    17. timer.Tick += Timer_Tick;
    18. backgroundImageX = step / 5;
    19. base.DoubleBuffered = true;
    20. }
    21. public void ToggleAnimation() => timer.Enabled = !timer.Enabled;
    22. public new void Dispose()
    23. {
    24. backgroundImage?.Dispose();
    25. timer.Stop();
    26. timer.Dispose();
    27. base.Dispose();
    28. }
    29. protected override void OnPaint(PaintEventArgs e)
    30. {
    31. base.OnPaint(e);
    32. e.Graphics.DrawImage(backgroundImage, backgroundImageX, 0);
    33. }
    34. protected override void OnResize(EventArgs eventargs)
    35. {
    36. base.OnResize(eventargs);
    37. SetBackgroundImage();
    38. }
    39. private void Timer_Tick(object sender, System.EventArgs e)
    40. {
    41. backgroundImageX += 0.5f;
    42. if (backgroundImageX >= 0)
    43. backgroundImageX = step / 5;
    44. Invalidate();
    45. }
    46. private void SetBackgroundImage()
    47. {
    48. backgroundImage?.Dispose();
    49. backgroundImage = new Bitmap(Width + (int)(step * -1), Height);
    50. using (Graphics g = Graphics.FromImage(backgroundImage))
    51. {
    52. using (Pen p = new Pen(ForeColor, 10))
    53. {
    54. p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
    55. g.DrawLine(p, 0, (Height / 2) - 5, Width + (step * -1), (Height / 2) - 5);
    56. }
    57. }
    58. }
    59. }
    60. }


    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Fakiz“ ()