Project-Outlook

WPF-Animation

Benutzerdefinierte Animationen mit WPF

Mit Hilfe von Windows Presentation Foundation (WPF) lassen sich unkompliziert einfache Animationen erzeugen. Soll die Animation abhängig von Bedingungen gesteuert werden, ist die Vorgehensweise komplexer.
Jede Aufgabe wird durch ein Fähnchen repräsentiert. Ist die Restlaufzeit der Aufgabe kleiner als 20 Tage, so beginnt das Fähnchen über das Brett zu wandern. Dies wird mittels einer Animation realisiert. Ist die Restlaufzeit genau an der 20 Tage-Grenze, so startet das Fähnchen an der vorderen Kante des Bretts. Bei einer erheblich kleineren Restlaufzeit muss das Fähnchen in einem Abstand zur vorderen Kante positioniert werden. Zusätzlich sollte es in dem Outlook-Addin möglich sein, das Datum tageweise vor- und zurückzuspulen.

Für die Realisierung wurde nach folgendem Konzept vorgegangen: Jedes Fähnchen wird mit einer 20 Tage andauernden Animation ausgestattet. Als Wegstrecke wurde die Distanz von der vorderen zur hinteren Kante des Bretts eingestellt.
Für die Verschiebung des Fähnchens durch die Restlaufzeit und des Datumsoffsets wird die Animation vor- und zurückgespult. Bei einer Restlaufzeit von über 20 Tagen wird die Animation gestoppt. Im Stopp-Zustand der Animation bleibt das Fähnchen an der vorderen Kante des Bretts.

Zusätzlich gibt es noch einen Sonderfall: Die Animation wird entweder während der Initialisierung oder durch eine Datumsverschiebung gestartet. Läuft das Addin so lange, dass die Restlaufzeit einer Aufgabe irgendwann kleiner als 20 Tage wird, muss die Animation nachträglich zur Laufzeit gestartet werden. Dies wurde mit Hilfe der Aktualisierungsfunktion für Uhrzeit und Datum auf der Addin-Oberfläche realisiert. Bei jeder minütlichen Änderung der Systemzeit wird überprüft, ob eine Aufgabe die 20 Tage Restlaufzeit unterschritten hat.

Ausschnitte aus dem Sourcecode

Hinweis: Die Codeausschnitte wurden aus Gründen der Übersichtlichkeit gekürzt.

Zu erst wird eine Animation erzeugt (Z6) und parametriert (Z7f). Zur Steuerung der Animation wird eine AnimationClock benötigt. Diese lässt sich nicht direkt über einen Konstruktor erstellen, sondern muss von der Animation abgeleitet werden (Z10). Durch das Hinzufügen der AnimationClock an ein TranslateTransform3D-Objekt wird das Fähnchen animiert (Z12ff).

  1. mvflag = new ModelVisual3D();
  2. mvflag.Content = flag;
  3.  
  4. //[...]
  5.  
  6. animationZ = new DoubleAnimation();
  7. animationZ.Duration = new Duration(TimeSpan.FromDays(this.TaskTimeLength));
  8. animationZ.By = -mycube.innerboardsize;
  9.  
  10. animClockZ = animationZ.CreateClock();
  11.  
  12. animTranslation = new TranslateTransform3D();
  13. animTranslation.ApplyAnimationClock(TranslateTransform3D.OffsetZProperty, animClockZ);
  14.  
  15. mvflag.Transform = animTranslation;
  16.  
  17. seek_and_start(animClockZ);

Zum Spulen der Animation wird die Funktion seek_and_start(AnimationClock, int) verwendet. Der übergebene Int-Wert enthält das Datumsoffset. Er wird während der Initialisierung auf 0 gesetzt (Z22). Durch die Änderung des Datumsoffsets oder durch die Zeitaktualisierung der Oberfläche (siehe oben, Sonderfall) wird die Funktion mit dem aktuellen Wert des Schiebereglers aufgerufen.

Um eine Animation zu starten, muss folgende Ungleichung gelten:

$\displaystyle{ Enddatum - Systemzeit < 20 d }$

Unter Berücksichtigung des Datumsoffsets wird die Ungleichung erweitert:

$\displaystyle{ Enddatum - (Systemzeit + Datumsoffset) < 20 d }$

Aus Umformung der letzten Ungleichung lässt sich das Offset für die AnimationClock berechnen (Z5ff):

$\displaystyle{ dateoffset = Enddatum - (Systemzeit + Datumsoffset) - 20 d }$

Das berechnete dateoffset ist die Zeit, auf welche die Animation zu spulen ist (Z13). Allerdings muss das dateoffset größer als 0 sein, da die AnimationClock nicht auf negative Zeiten eingestellt werden kann. Bei negativen Zeiten wird die Animation gestoppt (Z18). Die Steuerung der AnimationClock erfolgt über einen integrierten Controller (Z13, Z19).

Wie bereits im Sonderfall beschrieben, wird die Funktion seek_and_start() regelmäßig aufgerufen um Animationen zur Laufzeit zu starten. Dabei wird der Funktion immer wiederholt das gleiche Datumsoffset übergeben. Um zu verhindern, dass bereits korrekt laufende Animationen erneut eingestellt werden (Z13), gibt es eine zusätzliche if-Anweisung (Z11). Diese erlaubt das Spulen an einer Animation nur, wenn:

  • sich die Animation in einem Stopp-Zustand befindet. Durch das Spulen wird die Animation automatisch gestartet.
    - oder -
  • sich das Datumsoffset geändert hat. Dieser Fall tritt ein, wenn der Anwender den Schieberegler in der Oberfläche verändert.

Ist eine der Bedingungen erfüllt, so wird die Animation auf das berechnete dateoffset gespult (Z13).

  1. private void seek_and_start(AnimationClock clock, int days)
  2. {
  3.     TimeSpan dateoffset;
  4.  
  5.     dateoffset = task.Enddate.Subtract(
  6.         DateTime.Now.Add(TimeSpan.FromDays(days)));
  7.     dateoffset = (TimeSpan.FromDays(TaskTimeLength)).Subtract(dateoffset);
  8.  
  9.     if (dateoffset.TotalMinutes >= 0.0)
  10.     {
  11.         if (clock.CurrentState == ClockState.Stopped || days != olddays)
  12.         {
  13.             clock.Controller.SeekAlignedToLastTick(dateoffset,
  14.                 TimeSeekOrigin.BeginTime);
  15.             olddays = days;
  16.         }
  17.     }
  18.     else
  19.         clock.Controller.Stop();
  20. }
  21.  
  22. private void seek_and_start(AnimationClock clock) //standard parameters
  23. {
  24.     seek_and_start(clock, 0);
  25. }
  26.  
  27. //[...]
  28.  
  29. public double TaskTimeLength
  30. {
  31.     get
  32.     {
  33.         //represent 20 days on the board
  34.         return 20.0;
  35.     }
  36.  
  37. }

Erzeugen und Darstellen von 3D-Modellen in WPF | | Ergebnis der Arbeit

Options: