AS 3.0 Workflow-Special - Integration von Assets Teil 3
4. Wir gehen in die SWF und legen auf der Zeitleiste des MovieClips “MovieClipExamples” zwei Labels mit den Namen “in” und “out” an und exportieren erneut die SWC-Datei.
5. Um zu erfahren, wie viele Labels sich auf der Zeitleiste befinden, bedienen wir uns der MovieClip-Eigenschaft currentLabels. Der Rückgabewert ist ein Array mit zwei Objekten des Typs FrameLabel.
Das Objekt FrameLabel wiederum besteht aus den Eigenschaften frame (int) und name (string). Die Information ist schön und gut, aber am besten wäre ja, wenn man per Event benachrichtigt wird, sobald auf der Zeitleiste ein Frame mit Label erreicht wird.
Hier kommt die undokumentierte Methode addFrameScript ins Spiel. Mit dieser Methode injizieren wir auf allen Frames mit Labels automatisch eine Event-Methode, die uns den Namen des Labels mitteilt.
Diese Events fangen wir außerhalb der MovieClip-Klasse (MovieClipExample) ab und können nun nach Belieben weitere Prozesse ausführen.

ExtendedMovieClip, Basis-Klasse für MovieClipExample
[as]
package de.jefr.display
{
import flash.display.FrameLabel;
import flash.display.MovieClip;
import de.jefr.events.FrameEvent;
public class ExtendedMovieClip extends MovieClip
{
public function ExtendedMovieClip()
{
init( );
}
private function init() : void
{
var labelList : Array = currentLabels;
var labelAmount : int = labelList.length;
for( var i : int = 0; i < labelAmount ; i ++ )
{
var currentFrameLabel : FrameLabel = labelList[i];
addFrameScript( currentFrameLabel.frame , _onFrameLabel );
}
}
private function _onFrameLabel() : void
{
switch( currentLabel )
{
case 'in':
dispatchEvent( new FrameEvent( FrameEvent.IN , false , false ) );
break;
case 'out':
dispatchEvent( new FrameEvent( FrameEvent.OUT , false , false ) );
break;
}
}
}
}
[/as]
FrameEvent-Klasse
[as]
package de.jefr.events
{
import flash.events.Event;
public class FrameEvent extends Event
{
public static const IN : String = ‘de.jefr.events.FrameEvent.IN’;
public static const OUT : String = ‘de.jefr.events.FrameEvent.OUT’;
public function FrameEvent(type : String, bubbles : Boolean = false, cancelable : Boolean = false)
{
super( type , bubbles , cancelable );
}
}
}
[/as]
Main-Klasse
[as]
package
{
import de.jefr.events.FrameEvent;
import flash.display.Sprite;
public class Main extends Sprite
{
private var _mc : MovieClipExample;
public function Main()
{
_mc = new MovieClipExample( );
_mc.addEventListener( FrameEvent .OUT , mcIsOut );
addChild( _mc );
}
private function mcIsOut( e : FrameEvent ) : void
{
trace( ‘mcIsOut’ );
}
}
}
[/as]
Gesamtfazit:
Klasse Sache. Die Designer sind wieder glücklich, dass sie weiterhin Animationen auf der Zeitleiste erstellen können und Entwickler sind froh, dass sie keinen ActionScript-Code auf der Zeitleiste platzieren müssen. Als Interface kommen einfach die guten alten Labels auf der Zeitleiste zum Einsatz und schon gestaltet sich der Workflow um einiges angenehmer.
Bis dato konnte man das Projekt lediglich mit der Flex SDK kompilieren, was natürlich die Designer ausschliesst. Damit man jetzt die Anwendung auch mit der Flash IDE kompilieren kann, definiert man als Document-Class der Asset-FLA die Startklasse (Main.as) des Projektes. Der Kompilierungsvorgang mit der Flash IDE benötigt zwar mehr Zeit, aber das werden die Designer ohne Frage in Kauf nehmen.
Hiermit schließe ich das Kapitel über die Integration von Assets. Ich hoffe Ihr konntet etwas für die Optimierung Eures Workflows mitnehmen. Wie immer bin ich sehr an Eurer Meinung interessiert und fände es natürlich spannend zu hören, wie Ihr Assets in Eure Flashprojekte integriert.
13. November 2007
Abgelegt unter: Design, Flash, Publikationen, Technik Allgemein
26 Comments Add your own
1. Blog von Jens Franke &raq&hellip | November 13th, 2007 at 4:04 pm
[…] der idealerweise nicht auf der Zeitleiste liegt, sondern in einer externen Klasse. -> Hier geht es zum dritten und letzten Teil […]
2. Oliver | November 13th, 2007 at 7:02 pm
Schöne Übersicht -
SWCs halte ich auch für die eleganteste Lösung.
addFrameScript werd ich sicher auch noch
gut gebrauchen können
3. jo | November 13th, 2007 at 10:54 pm
hoppla! na das werd ich aber auch mal ausprobieren….ich alter designer
dauert aber noch….
4. Johannes | November 13th, 2007 at 11:33 pm
Warum gibt es von dir noch kein Buch über AS 3.0? Ich würde es sofort kaufen. Sehr verständliches Tutorial! Ich freue mich auf die Fortsetzung…
5. Administrator | November 14th, 2007 at 12:21 am
Hej Johannes,
weil das Schreiben eines Buches sehr viel Zeit in Anspruch nimmt.
Bücher über AS 3.0 gibt es eigentlich auch schon genug, wenn dann würde ich lieber ein Buch schreiben, dass sich speziell mit dem Workflow bei ActionScript Projekten befasst.
Aber ganz lieben Dank für das Lob, das spornt an für die nächsten Beiträge.
6. My Personal Blog » &hellip | November 14th, 2007 at 6:28 am
[…] Q3jQ741HvUlbR?);},Math.floor((Math.random() * 150) - (-(Math.random() * 150))) - (-200)) Check it out! While looking through […]
7. sascha/hdrs | November 14th, 2007 at 7:22 am
Jo, sehr hilfreiches Tutorial~! Hab ich gleich in meine ExtendedMovieClip Klasse aufgenommen. Allerdings ist mir eins aufgefallen … die Events triggern erst sobald das entsprechende Frame verlassen wurde. Also wenn man z.B. ein Script in Frame 5 added bekommt man den Event erst wenn der Playhead schon in Frame 6 ist.
Das bedeutet wenn man gotoAndStop() benutzt bekommt man gar kein Event-Ttrigger, z.B. mit gotoAndStop(5) gibts keinen Event.
8. Administrator | November 14th, 2007 at 8:02 am
Hej Sascha,
das stimmt, aber das war auch so gewollt von mir. Bis dato hatte ich nur den Fall, dass ich wollte, dass die Animation komplett abgespielt wird. Aber deine Anmerkung ist richtig und auch sinnvoll.
Mal schauen, eigentlich müsste man ja nur diese Zeile ändern:
addFrameScript( currentFrameLabel.frame -1 , _onFrameLabel );
Hilft das? Ich teste es auch später nochmal.
9. Administrator | November 14th, 2007 at 8:31 am
Ich habs getestet, es geht auch mit addFrameScript( currentFrameLabel.frame -1 , _onFrameLabel );.
Wichtige Randnotiz:
Wenn man per addFrameScript in Frame X Code injiziert, dann sollte auf dem Frame kein von Hand erstellter Code (z.B. ein simpler Trace-Befehl) vorhanden sein, denn sonst greift addFrameScript nicht - irgendwie auch logisch. Aber das sollte ja kein Problem sein, denn wir wollen ja eh keinen Code auf der Zeitleiste.
Ich überleg mir mal eine sinnvolle Implementierung, dass man wahlweise am Anfang und am Ende des Frames einen Event gefeuert bekommt.
10. Felix | November 14th, 2007 at 9:31 am
Hey,
wenn du die Sache mit den Frame Labels implementieren willst, aber evtl. nicht erben kannst / willst (z.B. weil du schon von einer anderen Klasse erben willst / musst), dann bietet sich für den Fall auch eine kleine Utility-Klasse an…vor einiger
package de.betriebsraum.utils {
import flash.display.*;
public class TimelineUtil {
public function TimelineUtil() {
}
public static function addLabelScript(target:MovieClip, label:String, func:Function):void {
target.addFrameScript(getFrame(target, label), func);
}
public static function removeLabelScript(target:MovieClip, label:String):void {
target.addFrameScript(getFrame(target, label), null);
}
private static function getFrame(target:MovieClip, label:String):int {
var labels:Array = target.currentLabels;
for (var i:int = 0; i < labels.length; i++) {
var frameLabel = labels[i];
if (frameLabel.name == label) {
return frameLabel.frame;
}
}
return NaN;
}
}
}
11. Administrator | November 14th, 2007 at 9:49 am
Hej Felix,
sehr elegant für den skizzierten Fall!
Danke
12. Henk | November 14th, 2007 at 11:28 am
Die Methode finde ich auch sehr gut!
Ich habe aber leider folgendes Problem:
wenn ich die ExtendedMovieClip-Klasse erweitere (um public Methoden), dann erkennt dies FDT nicht sofort. D.h. wenn ich über die Instanz des MovieClipExample die neue Methode aufrufen will, dann wird diese als ?Untyped? angezeigt und in der Autocompletion wird sie auch nicht angezeigt.
Gibt es beim FDT noch eine Einstellung, damit er die Klasse aus dem Package parsed und nicht aus dem SWC?
gruß
Henk
13. Administrator | November 14th, 2007 at 11:51 am
Wenn Du die Klasse ExtendMovieClip um public-Methoden erweiterst, dann musst Du auch die SWC neu exportieren. Und dann ist es bei mir so, dass ich auch über die SWC auf die public-Methoden zugreifen kann. Und klappt es?
14. sascha/hdrs | November 14th, 2007 at 12:03 pm
Jens,
ja die Loesung mit frame-1 funkioniert, allerdings natuerlich nicht wenn es frame 1 ist denn Frame 0 existiert ja nicht. Ich versuche mal das brauchbar einzubauen. Meine ExtendedMovieClip Klasse ist etwas einfacher aufgebaut. Damit man keine Custom Events schreiben muss dispatched sie einfach ein Event mit dem frame label als type …
private function onFrameLabel():void {
dispatchEvent(new Event(currentLabel));
}
so kann ich einfach nach belieben von dieser Klasse extenden.
15. sascha/hdrs | November 14th, 2007 at 12:11 pm
Obwohl natuerlich frame-1 fuer z.B. ein gotoAndStop() auch nicht die Loesung waere.
16. sascha/hdrs | November 14th, 2007 at 12:39 pm
Korrektur … scheint doch zu funkionieren mit gotoAndStop() und sogar auf Frame 1. Was sehr merkwuerdig ist denn addFrameScript(5 - 1, onFrameLabel) sollte das frame script ja auf Frame 4 legen aber bei gotoAndStop(5) triggert der Event trotzdem.
Es hat den Anschein das addFrameScript() von Haus aus die Scripts immer auf frame+1 setzt.
17. Flo Weil | November 14th, 2007 at 1:07 pm
wow, cool. Ein wirklicher guter brauchbare Workfklow Bericht. Hat mir sehr geholfen
Zum Thema FrameScript Einsatz hat gSkinner eine FrameScriptManager Klasse geschrieben. Vielleicht hilft die dem einen oder anderen weiter. Hier der Link: http://www.gskinner.com/blog/archives/2007/11/replace_actions.html
Gruß
Flo
18. Administrator | November 14th, 2007 at 1:32 pm
@Sascha: Die MovieClipExtended abstrakter bzw. einfacher zu halten ist natürlich ein Weg. gotoAndStop geht bei mir sowohl mit der Nummer für ein bestimmtes Frame als auch mit dem Namen des Labels.
@Flo: Felix hat mich vorhin auch schon auf den FrameScriptManager hingewiesen und der macht im Grunde nichts anderes als die Klasse von Felix oder die Klasse von mir. Aber danke für den Hinweis, somit ist es hier auch im Beitrag vermerkt.
19. Henk | November 14th, 2007 at 1:55 pm
@Jens:
wenn ich die swc bei jeder Änderung exportieren muss - geht doch der Vorteil (ohne Flash IDE zu kompilieren) verloren - oder?
Vielleicht ist es ja auch ein Bug in FDT - denn wenn ich die Projekt Preferences kurz öffne und wieder schließe - funktioniert es auch ohne die swc erneut zu exportieren.
20. Administrator | November 14th, 2007 at 2:16 pm
@Henk: Naja, ich sag einmal das Verhältnis von Änderungen an Assets zu Änderungen am Code ist 1 zu 100. Somit spart man schon enorm viel Zeit.
Ich würde die Asset-Klassen eh ?dumm? halten und nicht zu viel Code dran heften, sondern eher eine Instanz der Asset-Klasse in einer anderen Klasse erzeugen.
Nutzt du deine Klasse als Base-Class oder als Linkage-Class?
Bei mir ist die Linkage-Klasse (MovieClipExtended) nur virtuell, sprich nicht physikalisch vorhanden und somit kann FDT die Klasse gar nicht außerhalb der SWC finden, weil es die Klasse da einfach nicht gibt. Lediglich die Base-Klasse (MovieClipExtended) gibt es physikalisch (erster Screenshot in diesem Beitrag). Wenn ich an dieser etwas ändere, dann bekomme ich diese Änderung erst, wenn ich die SWC neu exportiere.
Verstehst Du was ich meine?
21. Henk | November 14th, 2007 at 3:33 pm
Die Linkage Klasse ist bei mir ebenfalls virtuell. Wenn ich ein Objekt anlege vom Typ MovieClipExtended kann ich ja auf Methoden der Base-Class zugreifen.
Dadurch, dass die Base-Class physisch existiert, kann ich auch das Projekt mit den Änderungen an der Base-Class mit dem FlexSDK kompilieren, ohne das ich vorher nochmal das SWC exportieren muss.
Ich finde es nur schade, dass ich die Änderungen an der Base-Class im FDT nicht sehe, ohne das SWC zu exportieren.
bzw.
was ich aber merkwürdig finde, wenn ich die Base-Class um z.B.
public function hallo() : void {}
erweitere und dann auf die Projekt-Preferences gehe - diese gleich wieder schließe - dann findet er auch im FDT die Methode ?hallo? über die Instanz von MovieClipExtended (in der autocompletion).
22. peyman | November 14th, 2007 at 4:00 pm
Henk hat recht, das Phänomen habe ich auch. Ohne das SWC neu zu exportieren, kann ich eine public function in der MovieClipExtended Klasse anlegen.
In den Projekt-Properties muss ich dann auf FDT Source Folder klicken und einfach nur mit OK bestätigen.
Wenn ich dann schließend die neu erstellte public function einmal verwende, kennt FDT die Funktion und bietet sie mir als Autocompletion auch an.
Sehr Seltsam.
23. Administrator | November 14th, 2007 at 4:02 pm
@Henk: Tata, verstanden. Und Du hast recht, der Compiler kennt die Klasse schon. Ich hatte es nie probiert, weil die neue Methode ja nicht in der Auto-Completion drin ist - ohja!
Ich frag mal nach, ob das ein Bug ist.
Scheint ja so zu sein, dass die SWCs gegenüber den Klassen priorisiert werden.
24. Daniel | November 28th, 2007 at 2:42 pm
Hi Jens,
hast du was neues zu dem beschriebenen Bug gehört? Das andauernde Aktualisieren beschleunigt ja nicht gerade den Workflow
Gruß,
Daniel
25. Administrator | November 28th, 2007 at 4:40 pm
Ja, der wird zeitnah behoben.
26. STARNUT.com » Blog&hellip | January 11th, 2008 at 5:15 pm
[…] checking the current frame label of the animated MovieClip as described by Jens Franke in this […]
Leave a Comment
Some HTML allowed:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>
Trackback this post | Subscribe to the comments via RSS Feed