Lange Animationen in Kapitel unterteilen mit ResourceDictionary und Wiederverwendung

Das unten geschilderte Verfahren ist besonders für den Anwendungsfall gedacht, dass eine langläufige Animation mit sich wiederholenden Elementen erzeugt werden soll. Vor dieser Herausforderung stand ich Anfang 2007, mit einer Menge Arbeit und Beta Werkzeugen vor mir. Diese Lösung mag eventuell auch manchen Programmierer noch interessieren, der als Amateur-Designer vor der Aufgabe steht, eine optimierte, schnelle Animation zu erzeugen.

Für den Kommunikationsriesen in Magenta wurde Vista zu einem kleinen Alptraum. Schließlich liefen seine wunderbaren Flash-Animationen auf den Install-CDs nicht mehr. Diese teilweise minutenlange Animationen galt es neu zu gestalten. Aber endlose Animationen in XAML sorgen für recht aufwändig zu pflegende und kaum wartbare Animationsdateien. Zwar kann man mit Hilfe der <ResourceDictionary.MergedDictionaries> die Resourcen wunderbar aufteilen. Doch dann sind da immer noch die langen Laufzeiten, wenn man ganz am Ende seiner 3,5 Minuten Animation ein Bild drei Pixel nach links schieben muss und mit Opacity Blending ausblenden soll.

In der bunten Theorie der Werbeankündigungen, soll der Expression Blend uns dabei unterstützen. Aber was Timeline, Layer oder andere Nettigkeiten betrifft, ist das Werkzeug von Microsoft den Flashworkbenchs einfach unterlegen und war Anfang Januar 2007 wirklich nicht frei von Bugs. Was bleibt ist die Realisierung im Visual Studio oder mit Hilfe der freundlichen Pads - meine Wenigkeit bevorzugt Visual Studio - wen wunderts, ich bin in der Hauptsache Programmierer und in der zweiten Reihe Designer. Aufgeteilt werden muss eine Animation (meine bestand aus 8 Kapitel mit je rund 30 Sekunden) immer noch.

<Window.Resources>      

    <ResourceDictionary>
      <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source=”Kapitel1.xaml”/>
        <ResourceDictionary Source=”Kapitel2.xaml”/>
        <ResourceDictionary Source=”Kapitel2.xaml”/>
        <ResourceDictionary Source=”Kapitel4.xaml”/>
        <ResourceDictionary Source=”Kapitel5.xaml”/>
        <ResourceDictionary Source=”Kapitel6.xaml”/>
        <ResourceDictionary Source=”Kapitel7.xaml”/>
        <ResourceDictionary Source=”Kapitel8.xaml”/>
      </ResourceDictionary.MergedDictionaries>
     </ResourceDictionary>      

  </Window.Resources>

Dann heißt es, die Startklasse meines Fensters mit zwei winzigen Funktionen zu versehen, die über den RoutedEvent “Loaded”

this.Loaded += new RoutedEventHandler(Start_Loaded);

gestartet werden .

#region Film
static int StartKapitel = 1;
static int AktuellesKapitel = -1;
static int EndKapitel = 8;
private Storyboard findMovie(string key)
{
    if (this.Resources.Contains(key) == true)
        return this.Resources[key] as Storyboard;   

    foreach (ResourceDictionary resourceDic in
    this.Resources.MergedDictionaries)
    {
        if (this.Resources.Contains(key) == true)
            return this.Resources[key] as Storyboard;
    }
    MessageBox.Show(“Kann “ + key + ” nicht finden”,
    “Schwerer Fehler”, MessageBoxButton.OK,
     MessageBoxImage.Error);
    return null;
}   

public void DoTheMovie(object sender, EventArgs args)
{
    if (AktuellesKapitel == -1)
        AktuellesKapitel = StartKapitel;
    if (AktuellesKapitel > EndKapitel)
        return;   

    string key = “Kapitel” + AktuellesKapitel;
    Storyboard movie = null;
    movie = findMovie(key);
    if (movie != null)
    {
        movie.Completed += new EventHandler(DoTheMovie);
        movie.Begin(this);
    }
    AktuellesKapitel++;
}   

#endregion

Klein aber fein suchen die Funktionen nach den Storyboards mit dem einfallsreichem Namen “Kapitel1″ bis “Kapitel8″. Werden die Storyboards gefunden, so werden sie gestartet nachdem sich die Funktion selber als Completed EventHandler eingetragen hat. Somit erfährt die Funktion selber, wann das Kapitel beendet ist und kann das nächste starten. Raffiniert wird es dann, wenn man seine Animation so plant, dass man in die späteren Kapitel springen kann. Doch dazu sollte man zwingend den Designer nun endlich aus der Hand legen. 

Der Trick mit der Wiederverwendung 

Bei der vorliegenden 3,5 Minuten Animation komme ich mit 33 graphischen GUI Elementen aus. Mehr verwende ich nicht. Der große Trick heißt Wiederverwendung der vorhandenen Elemente. Jedes Kapitel beginnt mit der gleichen Ausgangslage. Dafür sorgen am Anfang des Kapitels “DiscreteObjectKeyFrame”, die alle Objekte auf Hidden schalten, “DiscreteDoubleKeyFrame”, die Größe und Position setzen und “DiscreteStringKeyFrame”, die neue Texte einspielen. Dann werden mit “DiscreteObjectKeyFrame” die Hintegründe in Canvas eingebaut. Ich verwende grundsätzlich keine Image-Elemente, da Canvas weitaus flexibler einsetzbar sind. Somit verändert sich jedes Element während der Animation mehrfach, erhält neue Rollen und Aufgaben. Wird nahezu endlos wieder verwendet.

Was auf den ersten Blick umständlich und mühsam erscheint, wird schnell zu einer effektiven Erstellung der Animation. Denn durch die Unterteilung in Kapitel, die jeweils die gleiche Ausgangssituation haben, lässt sich bereits erstellter Animationscode kopieren und leicht modifiziert wieder verwenden. Ob nun das Bild “Fröhlicher Surfer.jpg” oder das Bild “Glücklicher Flatratnutzer.jpg” gezeigt wird, interessiert die Animation, welche sich mit dem Canvas “Bild1″ beschäftigt herzlich wenig.

In den meisten Fällen unterscheidet sich eine Animation von der vorherigen nur durch wenige Parameter, oft ist es nur der Hintergrund oder der Text. Somit kann man durch die Unterteilung in Kapitel, die man mit der Hand bearbeitet erstaunlich viel Zeit sparen. Die 3,5 Minuten Animation war nach 2,5 Tagen fertig und ging anstandslos durch die QS.

Filed under: , ,

Comments

No Comments

Leave a Comment

(required) 
(required) 
(optional)
(required)