Erkennen von transparenten und opaken Pixeln in ActionScript

Oft bekommt man als Entwickler ein .png, das als Button dienen soll. Hier ist wie immer der einfache Weg, Bild einbinden und den Container klickbar machen. Das ist ja soweit kein Hexenwerk. Jedoch kann das zu unschönen Effekten führen, da natürlich auch die transparenten Teile des Bildes Klickbar sind und somit Bereiche interaktiv, die rein optisch gesehen, nicht mehr zum im Bild enthaltenen Objekt gehören.

Klar kann man jedes mal eine Überprüfung des unter dem Mauszeiger liegenden Pixels machen und prüfen ob dieser nun transparent ist oder eben nicht. Aber es wäre doch schön, einfach eine Fläche zu haben, die man als ClickArea über das Bild legen kan, um darauf die MouseListener zu legen, ohne jedes Mal irgendwas abzuprüfen, was eventuell zu unschönen Seiteneffekten führt.

Die simple Variante hierfür ist eine BoundingBox zu generieren, welches das Rectangle repäsentiert, in dem die opaken Flächen liegen. Für hauptsächlich rechteckige Formen sollte das ausreichend sein. Aber was ist wenn, die Form komplexer ist oder einfach nicht Rechteckig? Das führt dann zu folgendem Ergebnis:

This movie requires Flash Player 9

Das ist bei dieser Form kein wirklich akzeptables Ergebnis. Man hätte sich hier auch einfach die Mühe sparen können. Also benötigt es einen anderen Ansatz, die eine Annäherung an die Form ermöglicht und so eine bessere BoundingBox zurückliefert.

Das Ansatz dazu klingt recht einfach. Man unterteilt das Bild in vier gleiche Rechtecke und schau nach, wie es mit den Transparenzen innerhalb der Fläche aussieht. Da gibt es drei Möglichkeiten: nur transparente, nur opake oder beides gemischte Pixel. Wenn es nur transparente Pixel sind, muss dieser Teil der Bildes nicht weiter untersucht werden. Genau das selbe gilt für die opaken Pixel. Jedoch sollte man sich hier den Bereich merken, da er ja zur BoundingBox des Bildes gehört, die ja Ziel der ganzen Aktion ist.

Bei den Rechtecken mit transparenten und opaken Pixeln muss man einfach wieder unterteilen und untersuchen. Dies sollte man aber nicht zu oft durchführen, da sich der Summe der Untersuchungen natürlich jedes mal vervierfacht. Im folgenden Beispiel habe ich 8 Iterationen verwendet, was zu einem recht guten Ergebnis führt:

This movie requires Flash Player 9

Die Überprüfung auf transparente und nicht transparente Pixel ist eigentlch recht einfach. Man nutzt das Rechteck aus der Unterteilung und führt die BitmapData.getPixels-Methode aus. Diese liefert einen ByteArray aller Farbwerte im Rechteck zurück und zwar 32-Bit. Über readUnsignedInt() bekommt man aus diesen wiederum die Farbwerte und kann diese über „>>> 24“ (Unsigned right shift) um eben 24 Bit nach rechts verschieben, womit der Alphakanal übrig bleibt. Hier bildet man die Quersumme der Alphawerte. Sollten diese 0x00 sein ist der Bildteil transparent, ist er 0xFF ist er eben opak. Hier lassen sich dann auch Toleranzen einfügen. Für die doch recht üppige Menge an Überprüfungen, ist es im übrigen besser eine Linked List zu nutzen, anstatt eines Arrays oder ArrayCollection.

Das ganze führt dann zu folgendem Ergebnis (grün sind die voll opaken Bereiche, die blauen die Randbereiche, die bei der letzten Iteration übrig bleiben):

This movie requires Flash Player 9

FlashForum Konferenz 2010 – Community. Code. Creativity.

Auch dieses Jahr hatte ich die Möglichkeit die FFK zu besuchen, nachdem ich letztes Jahr bereits dort war. Auch Jürgen war diesemal mit dabei. Zwei Tage voller Vorträge über Flash, Flex und ActionScript, aber auch über Themen die über das reine Coding hinausgehen. Also eine breitgefächerte Themenwahl, welche jeden Flasher und Flexer in gewissem Maße betreffen.

Um es gleich Vorweg zu nehmen: Es war der Hammer. Die Fülle an Eindrücken, von neuen Ideen, Technologien und Ansätzen war wieder immens und macht wiederum klar wie mächtig eigentlich die Flash Platform ist. Aber auch die Selbstverständlichkeit im fast schon familiären Umgang der Coder untereinander war wieder beindruckend. Wann hat man denn schon die Möglichkeit die „Größen“ der Szene zu treffen und mit ihnen alltägliche Coderprobleme zu besprechen.

Dieser Text soll nun nur einen kleine Überblick sein, was ich an Themen mitbekommen hab in den Vorträgen. Ich denke in der nächsten Zeit werden Jürgen und ich immer mal wieder ein Thema hier von auf diesem Blog behandeln. Serge Jespers eröffnete die FFK und stellte unter anderem die Flash Platform Services vor. Interessant hier vor allem die Bereiche Distribution und Collaboration. Die ebenfalls dazugehörenden Social Services waren schon aus dem com.adobe Package bekannt.

Ich möchte jetzt nicht auf jeden Vortrag eingehen den ich gesehen habe. Aber ein paar Highlights für mich herauspicken. Dazu zählt unter anderm der Vortag von Michael Wacker „Mind the gaps“, der das Themas Flash Security hatte. Eine richtig gute Anregung und ein Fingerzeig für die Community, was es noch mangelt. Ganz klar mit dabei bei meinen Favoriten mit dabei Andre Michelles „Tanzen mit Krücken“. Sehr beeindruckend, vor allem interessant, dass immer mal wieder Tipps und Trick durchsickerten, wie SWFs schnelle und sicherer Laufen. Aber dies nicht nur bei ihm. Auch Saban Ünlü oder Ralph Hauwert mit seinen experimentellen Animationen, ließen hier und da immer wieder ein paar Worte dazu fallen.

Aber auch Bereiche wie Performance Tuning, Usability Testing, Aufbau von Software für Multitouch Devices waren Themen auf der FFK. Richtig beeindruckend, wie schon letztes Jahr, die beiden Vorträge von Joa Ebert und Mario Klingemann. Joas „Apparat“ ist kurz gesagt einfach der Hammer. SWF ByteCode Optimierung um so noch mehr auf Flash rauszuholen und noch schnelle Animationen laufen lassen zu können. Der experimentelle und künstlerische Ansatz von Mario versetzt jeden Flasher immer wieder in Staunen.

Der für mich am interessanteste Vortrag war aber von Jens Halm: „Enterprise Applications mit dem Parsley Application Framework“. Ich hatte davor wenig gehört von Inversion of Control und der ganzen Thematik die hier vorgestellt wurde. Aber der Ansatz der Modularisierung des Codes und der Vereinfachung der Zugriffe und Abhängigkeiten, vor allem die Implementierung in Cairngorm 3 haben mich hellhörig gemacht. Ein Ansatz der Programmierung der mir sehr entgegen kommt und vor allem auch den Workflow des einzelnen und eines ganzen Teams, aber auch das Testen von Apps und Teilbereiche deren immens vereinfacht und verbessert.

Ich könnte jetzt so noch ewig weiter schreiben, da beide Tage voll solche Eindrücke waren. Aber wie gesagt, in nächster Zeit gibt es hier immer wieder ein paar Auszüge davon. Nur eins noch: Ich warte jetzt schon auf die FFK 2011!

http://ffk10.flashforum.de/
http://www.adobe.com/flashplatform/services/

Farben in ActionScript

Neben der weitgehenden Browserunabhängigkeit bietet ein SWF dem Entwickler auch die Möglichkeit, Umgebungen zu schaffen die den User zu begeistern. Der Weg dorthin ist vielfältig. So sind, im Vergleich zu HTML, die freie Schriftwahl, einfach zu erstellende Animationen oder die Integration verschiedenster Medien wichtige Bestandteile davon. Aber auch der richtige Umgang mit Farben ist ungemein wichtig.

Farbe ist in ActionScript nicht nur einfach eine bunte Fläche. Das ist was der User am Bildschirm sieht. Jede Farbe ist letztlich ein HEX-Code. So lässt sich weiß zum Beispiel mit 0xFFFFFF aus drücken oder wenn eine Alphakanal dabei sein soll eben 0xFFFFFFFF.

Beschränken wir uns aber zunächst auf den RGB-Raum ohne Alphakanal. Jeder Farbkanal umfasst einen Bereich von 0 (0x00) bis 255 (0xFF), oder binär ausgedrückt 0 bis 11111111. Durch diese Definition kommen die fast 16,6 Millionen Farben zusammen, denn 255 * 255 * 255 ergibt eben fast 16,6 Millionen. Und mit 16 Millionen Farben lässt sich wirklich einiges Anfangen.

Zu beachten ist aber, bevor man anfängt mit Farben zu rechnen, dass Farben im 16er-System definiert sind und nicht, wie der normale Mensche rechnet, im 10er-System. Um die Farben ausgeben zu können ist es daher notwändig anzugeben in welchen Zahlensystem. Gibt man den Farbwert einfach über einen trace aus, schreibt der FlashPlayer den Wert im 10er-System. Will man aber eine hexadezimale oder binäre Ausgabe, muss man die toString-Methode nutzen, wobei hier als Parameter das System angegeben werden kann (z.B. 16 für hexadezimal).

Will man die einzelnen Känale getrennt von einander bearbeiten, muss die Farbwert zerlegt werden. Dafür werden bitweise Operatoren benötigt. Will man nun den Wert für den grünen Kanal auslesen sieht das Script dazu wie folgt aus:

var baseColor:uint = 0x4598FF;
var green:unit = (baseColor & 0x00FF00) >> 8;
trace (green.toString(16)); // 0x98

Um das kurz zu erklären: Zunächst nimmt man die Ausgangsfarbe und entfernt alle Farbwerte, außer die grünen, durch den logischen AND-Operator (&). And ist so definiert, dass, nur wenn beide miteinander zu „verundende“ Bits den Wert 1 haben, das Ergebnis 1 zurückgegeben wird. Deswegen gibt diese Rechnung nur die grünen Werte zurück. Anschließend werden die Bits noch um 8 Stellen nach rechts verschoben, damit die grünen Werte am Ende stehen. Diese Prozedur ist für alle anderen Farbbereiche die selbe.

Hat man nun alle seine Berechnung durchgeführt und will die einzelnen Känale wieder zusammensetzen geschieht auch dies wieder mit bitweisen Operatoren:

var color:uint = alpha << 24 | red << 16 | green << 8 | blue;

Hier nimmt man die Werte für die einzelnen Känale schiebt sie soweit, wie eben eine ARBG oder RGB Farbe definiert ist und „verodert“ die einzelnen Werte. Das logische oder sagt aus, dass sobald eines der beiden zu vergleichenden Bits 1 ist, das Ergebnis 1 zurück gegeben wird. Wie die einzelnen nun Farben berechnet werden, ist jedem Entwickler freigestellt. Nur eben die oben gezeigt Basics müssen beachtet werden, dmait die richtigen Farben zu sehen sind.

Aber nicht alles muss berechnet werden. So bietet die TweenMax-Bibliothek auch schon die Möglichkeit Farbtweens zu scripten:

TweenMax.to(colors, 0.15, {hexColors:{targetColor}, onUpdate:updateColorizedObject});

Hier ist colors ein Object das einen oder möglicherweise mehrere Farbwerte einhält. TweenMax macht dann einen Tween über die Farbe. Dabei werden Update-Events dispatched und im Handler lässt sich der aktuelle Farbewert aus colors wiederum auslesen.

Auch ein interessante Ansatz Farben zu verändern ist der ColorMatrixFilter. Dieser ist als 4×5 Matrix definiert und ist ein BitmapFilter. Mit Hilfe dieser Matrix lässt sich aber nicht nur die Farbe verändern sondern auch die Sättigung und die Luminanz. Anwendbar ist dieser filter auf jedes DisplayObject.
Weiter auf diese Klasse einzugehen ist aber wiederum ein eigener Blogeintrag wert.

http://blog.greensock.com/tweenmaxas3/
http://www.adobe.com/devnet/flash/articles/bitwise_operators_03.html
http://help.adobe.com/de_DE/AS3LCR/Flash_10.0/flash/filters/ColorMatrixFilter.html

Aus Flash & Flex generierte PDFs

Oft ist es doch so, dass innerhalb einer Flash oder Flex Applikation PDFs zum download angeboten werden sollen. Sind diese fest auf dem Server hinterlegt, ist dies kein Problem. Einen Link darauf setzen und das Problem ist gelöst. Doch was nun, wenn die Inhalte aus dem SWF dazu dienen sollen, das PDF zu erzeugen. Dann wird es schon interessanter.

Ohne eine serverseitige Programmierung geht hier nichts. Zum Beispiel Java oder PHP müssen zur Hilfe genommen werden. Ärgerlich und vor allem umständlich wenn es darum geht, das PDF und die auf dem Screen enthaltenen Inhalte zu synchronisieren. Es muss hier nun überlegt werden, welche Informationen sende ich wie an den Server, um das Ergebnis zu reproduzieren, welches clientseitig eigentlich schon da ist. Wie gesagt sehr umständlich.

Thibault Imbert hat hier einen Ansatz geschaffen, der es Flash und Flex Entwicklern ermöglicht, PDFs clientseitig zu generieren. Nur ein kleines PHP Script ist noch nötig, um das PDF fertig zu stellen. Dieses ist im Package schon enthalten und fertig zum nutzen. AlivePDF heißt dieses Package und ist, was die Entwicklergemeinde freut, open source. Und die Handhabung des ganzen ist denkbar einfach.

var pdf:PDF = new PDF(orientation:String, unit:String, pageSize:Object=null, rotation:int=0);

Mit dieser Zeile ist das Grundgerüst der PDF schon erstellt, wobei orientation Hoch- oder Querformat definiert, unit das Maß in dem das PDF angelegt wird (Pixel, mm, ..), pageSize definiert die Seitengrößen (A4, A3, usw.) und letztlich rotation die Drehung der Inhalte als letzten Parameter. Für die ersten drei gibt es Klassen mit statischen Variablen zur Definition. Interessant ist hier die Size-Klasse, die sich recht leicht um weitere Seitengrößen erweitern lässt.

pdf.setDisplayMode (zoom:String = "FullWidth", layout:String = "SinglePage", mode:String = "UseNone");

Hiermit lässt sich definieren wie die Seite selbst dargestellt werden soll. Mit zoom zum Beispiel ist die Vergößerung der Anzeige definiert oder mit layout das Layout des Dokumentes selbst. Einfache Seite, eine Spalte oder zwei Spalten links sind mögliche Parameter.

pdf.addPage(page:Page = null);

Hiermit wird eine Seite im PDF hinzugefügt, der dann schlussendlich die Inhalte hinzugefügt werden. Als Parameter ist es möglich ein Page-Objekt mitzugeben, welches wiederum andere Größen- und Formatausrichtungen haben kann, als das PDF selbst. Damit können im PDF auch unterschiedliche Seitengrößen erzeugt werden, je nach dem was gerade benötigt wird.

Nun ist die erste Seite erzeugt und lässt sich mit Inhalten befüllen. Dabei gibt es Funktionen zur allgemeinen Seitendefinition (z.B. setRightMargin) oder eben um Inhalte einzufügen. Dabei können Grafikobjekte wie Kreise, Flächen oder Pfade erzeugt werden, wobei hier die sehr große Ähnlichkeit zu den Graphics-Funktionen den Workflow von vorne herein einfach gestalten. Aber auch Texte oder Bilder können eingefügt werden. Aber auf all diese Funktionen nun einzugehen, würde jeden Rahmen sprengen.

Um nun aus dem PDF-Objekt ein richtiges PDF zu machen, wird nun das create.php aus dem Package benötigt. An diese sendet man den erzeugten ByteCode und das php-File sagt dem ByteStream: „Du bist ein PDF und jetzt kann man dich runterladen.“ Das war es auch schon. Wie gesagt sehr einfach gehalten.

Um es kurz zusammen zu fassen, es gibt eine unglaubliche Masse an Funktionen und Einstellungsmöglichkeiten, dabei handelt es sich bei der aktuellen Version von AlivePDF um eine Alpha-Version und bisher ist mir noch kein Fehler untergekommen. Also hat Thibault ganze Arbeit geleistet! Vieles ist noch immer etwas experimentell, da die Dokumentation noch nicht sehr weit gediehen ist, aber bei einer Alpha Version ist dies glaub zu verkraften. Insgesamt also schon jetzt ein sehr gelungenes Werk.

Noch ein paar Links zum Thema:
www.alivepdf.org
Dokumentation
Download

Und drei kleine Videotutorials:
Getting Started
Flex & AlivePDF
Introduction on Adobe TV

Google Analytics für Flash und Flex

Google Analytics ist ein mächtiges Tool um das Nutzerverhalten innerhalb einer Seite zu untersuchen. Wo klickt der User, welche Themen sind besonders interessant und wie kann die Seite für den Nutzer optimiert werden? Dies sind nur ein paar Punkte bei denen Google Analytics hilfreich zur Seite steht.

Bei Flash und Flex Anwendungen war hier bisher Schluss. Die Seite wird aufgerufen, das SWF geladen und dies war der letzte Aufruf des Trackers, wenn der User sich ab nun innerhalb der SWF bewegt. Ein Zustand der jeden Marketingmenschen zur Verzweiflung treibt.

public var gaTracker:GATracker;

Der hier aufgeführte GATracker ist der Kern des com.google.analytics – Packages. Es enthält alle notwendigen Klassen um Google Analytics auf einer Flash oder Flex Anwendung anzusprechen. Dazu wird wie oben beschrieben eine Variable der GATracker erstellt. Über diese läuft dann die gesamte Kommunikation.
Nur wird bei applicationComplete (Flex) oder eben im Konstruktor (Flash) die oben beschriebene Variable instanziiert. Dazu müssen verschiedene Parameter mitgegeben werden damit die Kommunikation zu Google Analytics auch so funktioniert wie es soll. Wenn die Flash oder Flex Anwendung und auf dem MVC-Model basiert, bietet es sich zu dem an, die Tracker Variable im Model anzulegen. So lässt sie sich von überall nutzen.

Um nun aber auf die Parameter der Instanziierung einzugehen:

gaTracker = new GATracker(this, 'XX-XXXXXXX-X', TrackerMode.AS3, true);

Dies beschreebt die Instanziierung der GATrackers via ActionScript. Wobei ‚this‘ das parent DisplayObject darstellt. Ich denke dass es sinnvoll ist, mit this auf root der SWF zu verweisen. Als nächstes kommt der Google Analytics-Account. Diese ID einfach hier als String eintragen. Nun wird es interessanter. Der dritte Parameter beschreibt den TrackerMode ausgehened von der App. Dabei gibt es zwei Modi: TrackerMode.AS3 oder TrackerMode.BRIDGE. Dabei lässt es sich recht einfach unterscheiden, welchen Modus man verwenden soll. Der BRIDGE Modus wird genutzt, wenn in der HTML-Seite, in welche das SWF eingebettet wird, bereits ein Google Analytics-Tracker vorhanden ist. Dieser Tracker wird im BRIDGE-Modus über External-Interface angesprochen und dann auch für die Kommunikation zu Google Analytics genutzt. Der AS3-Modus wird hingegen genutzt, wenn kein Tracker in der HTML-Seite vorhanden ist. Der letzte Parameter sagt aus, ob der Tracker im Debug-Modus laufen soll oder nicht. Dies ist besonders interessant während der Entwicklung um zu überwachen welche Informationen gesendet werden.

Für die Flex-MXML Syntax gibt es einen eigenen Tag zum implementieren:

Hier verhalten sich die Attribute wie oben beschrieben, nur eben das es keinen Verweis auf das DisplayObject gibt, da der Tag sowieso schon in einem liegt. Hinzu kommt aber eine ID um den Tracker aufrufen zu können.

Wie wird nun die Userinteraktion an Google Analytics übertragen? Um es vorweg zu sagen, man kann als Entwickler definieren was alles getrackt werden soll und wie es ankommt. So ließe sich zum Beispiel vom MouseClick bis hin zur kleinsten Mausbewegung alles mittracken. Das dies (meist) nicht sinnvoll ist, ist klar aber es zeigt auf, welche Möglichkeiten es gibt.

Es gibt zwei Aufrufe zum senden von Informationen. trackPageview und trackEvent. Mit dem ersten wird GoogleAnalytics eine Information übermittelt, entsprechend dazu, wenn der User auf eine andere Seite navigieren würde:

gaTracker.trackPageview("/aFakePage");

Dabei wird die „neue“ Verzeichnisstruktur in der sich der User befindet, an Google übermittelt. Eben so als hätte sich die URL verändert.
Die zweite Möglichkeit dient dazu interne Events der RIA zu übermitteln, die nicht von der Usernavigation ausgehen.

gaTracker.trackEvent('category', 'action', 'label', [value:optional]);

Hier entspricht die „category“ der Gruppe zu der der Event zugeordnet werden soll und die „action“ ist inhaltlich an die „categorie“ gebunden. Das heißt, wenn es sich um Events handelt, die beispielsweise von einer Videosteuerung ausgehen, ist es sinnvoll die „category“ ‚video‘ zu nennen und the „actions“ wären zum Beispiel „play“, „pause“ und so weiter. Das „label“ bietet die Möglichkeit weitere Informationen zum category-action-Paar zu übermitteln, ebenso wie über „value„, wobei es sich hier um einen positiven Integer handeln muss.

Insgesamt eine sehr einfache Variante, um aus einem SWF heraus zu Google Analytics zu kommunizieren. Letztendlich würden sorgar zwei Zeile Code ausreichen, um den Datenaustausch zu erstellen. Das Package gibt es im übrigen zum Download bei GoogleCode.

Links:
http://code.google.com/p/gaforflash/
http://www.insideria.com/2009/02/using-google-analytics-within.html

Flex: Schriften zur Laufzeit laden

Um Schriften korrekt in Flex / Flash darstellen zu können, vor allem wenn Transparenzen oder Effekte darauf angewendet werden sollen, müssen sie in das swf eingebettet sein. Das Einbetten von Schriften verlängert allerdings die Kompilierungszeit und vergrößert die Dateigröße des SWFs enorm. Um dieses Problem zu umgehen können Schriften in ein eigenes SWF eingebettet werden, das dann zur Laufzeit geladen wird.

Vorgehensweise
Über den @font-face tag wird die Schrift in eine externe CSS Datei eingebettet.

@font-face {
  fontFamily: Arial;
  fontWeight: normal;
  src: url("Arial.ttf");
}

Der Flash / Flex Builder bietet die Möglichkeit CSS Dateien direkt als SWFs zu kompilieren.

Über das Kontextmenü lässt sich das CSS als SWF kompilieren
Über das Kontextmenü lässt sich das CSS als SWF kompilieren

Das erstellte SWF kann dann über den StyleManager geladen werden:

StyleManager.loadStyleDeclarations('fonts/Arial.swf');

Sobald die Schrift geladen ist kann diese verwendet werden. Darum sollte dieser Aufruf am Besten im initialize Handler der Hauptapplikation stehen. Wenn die Schrift erst später verwendet wird kann man sie natürlich auch erst laden wenn man sie wirklich braucht. Das macht vor allem Sinn wenn viele verschiedene Schriften verwendet werden, es aber nicht sicher ist ob alle Schriften tatsächlich gebraucht werden.
Mit Hilfe der Font Klasse lässt sich nachprüfen welche Schriften bereits geladen und verfügbar sind und zwar mit folgender Funktion:

Font.enumerateFonts(enumerateDeviceFonts:Boolean=false):Array

Es wird ein Array zurückgegeben das alle verfügbaren Schriften enthält. Standardmäßig werden nur die eingebetteten Schriften angezeigt (Der Parameter ist Standardmäßig auf false). Wenn dieser Parameter auf true gesetzt wird werden auch alle auf dem System installierten Schriften angezeigt.

Hier nochmal das ganze Beispiel

/**
 * Event handler for the initialize event of the main application.
 */
private function initializeHandler(event:FlexEvent):void {
	var e:IEventDispatcher = StyleManager.loadStyleDeclarations('fonts/Arial.swf');
	e.addEventListener(StyleEvent.COMPLETE,styleLoadedHandler);
}
/**
 * Event handler for the complete event of the StyleManager.loadStyleDeclarations function.
 * Traces all embedded fonts.
 */
private function styleLoadedHandler(event:StyleEvent) : void {
	var embeddedFonts:Array = Font.enumerateFonts(false);
	embeddedFonts.sortOn('fontName',Array.CASEINSENSITIVE);
	for(var i:Number = 0; i < embeddedFonts.length; i++){
		var item:Font = embeddedFonts[i];
		trace("[" + i + "] name:" + item.fontName + ", style: " + item.fontStyle + ", type: " + item.fontType);
	}
}

Wenn man die Kompilierungszeit des Flex Projekts beschleunigen will muss sich entweder das CSS das zum SWF kompiliert wird in einem eigenen Projekt befinden, oder der Haken vor „Compile CSS to SWF“ im Kontextmenu muss wieder entfernt werden. Ansonsten wird das CSS jedesmal wenn das Projekt gebuildet wird auch kompiliert. Und man hat keine Zeitersparnis. Eine gute Möglichkeit ist, den bin-debug Ordner des Schriften Projekts direkt in den html-template Ordner des eigentlichen Projekts zu legen. So werden die Schriften immer gleich am richtigen Ort abgelegt.

Erster Erfahrungsbericht zu Flex4

Wurde in Flex3 und den Vorgängern nur ein Namespace benutzt(„mx“) so muss man sich in Flex4 jetzt mit 3 auseinadersetzen. Das sollte aber kein Nachteil sein, ganz im Gegenteil, zum neuen MXML2009 Namespace gibt es jetzt die Spark und Halo Namespaces. Ein besonderes Augenmerk bekommt hierbei der Namespace Spark, dieser  enthält alle neuen Spark Komponenten (überarbeiteten Komponenten) und wird in Verbindung mit der MXML2009 verwendet. Das erste was bei Flex4 auffällt, es gibt keine Box, HBox, VBox wie man sie noch aus Flex3 kennt. Hier ein Beispiel zur alten Schreibweise im Aufbau einer Box

<mx:Box
	width="100"
	height="100"
	backgroundColor="0x0FF00F"
	>
	...
</mx:Box>

Hier ein Beispiel zur Flex4 verwendeten Schreibweise

<s:Group
	width="50"
	height="100"
	>

<s:Rect
	width="100%"
	height="100%"
	>
<s:fill>
	<mx:SolidColor
		color="0xFFFFFF"
		/>
</s:fill>
</s:Rect>
...
</s:Group>

eine Änderungen die gleich ins Auge springt. Desweiteren kann man zusätzlich das Layout der Group definieren,
hier gibt es 3 Layouts welche man verwenden kann. Es gibt einerseits das BasicLayout, dessen Verhalten mit dem aus Flex3 bekannten Canvas vergleichbar ist. Andererseits gibt es das HorizontalLayout und VerticalLayout, wie uns der Name schon verrät, handelt es sich hier um die horizontale bzw. vertikale Anordnung der Inhalte, vergleichbar mit der HBox oder VBox von Flex3. Für die letzten 2 Layouts kann man aber auch die VGroup oder HGroup verwenden.
Hier ein bsp. wie das ganze dann aussehen sollte

<s:Group
	width="50"
	height="100"
	>
<s:Layout>
       <s:VerticalLayout />
</s:Layout>
<s:Rect
	width="100%"
	height="100%"
	>
<s:fill>
	<mx:SolidColor
		color="0xFFFFFF"
		/>
</s:fill>
</s:Rect>
...
</s:Group>

Den genauen Unterschied zwischen VGroup und Group mit VerticalLayout bzw. HGroup und Group mit HorizontalLayout kann ich zum jetztigen Zeitpunkt leider noch nicht sagen. Weitere Erfahrungsbericht kommen sobald Flex4 ausführlich getestet wurde.

Flash und Flex debuggen mit dem De MonsterDebugger

Der De MonsterDebugger ist ein Open Source Projekt des Design Studios De Monsters.

Der Debugger ist in Flex realisiert und wird AIR Applikation verwendet. Diese stellt alle Objekte einer laufenden Flash, Flex oder AIR Applikation in einer übersichtlichen Baumstruktur dar, vergleichbar mit dem Debugger des Flex Builders / Flash Builders.

Der Vorteil zum Flex Debugger ist allerdingst, dass Properties der Instanzen direkt geändert werden können und diese Änderungen Live in der Applikation sichtbar sind (bekannt aus der Firefox Erweiterung FireBug). Außerdem werden alle Funktionen angezeigt und diese können zur Laufzeit ausgeführt werden.
Der Debugger enthält eine eigene trace Funktion die nicht nur Strings ausgeben kann sondern Objekte als Baumstruktur aufschlüsselt, also eine wesentlich übersichtlichere Darstellung als wenn man sich ein Objekt mit ObjectUtil.toString() ausgeben lässt.

Ein Großer Nachteil ist, dass nur Properties und Funktionen die auf public gesetzt sind angezeigt und werden können. Der Debugger verwendet intern die Funktion describeType(myObject) : XML die eine XML Struktur über das Object zurückgibt. Hier werden allerdings nur alle Properties und Funktionen die public sind ausgegeben.
Der Debugger unterstützt auch keine Breakpoints wie ein klassischer Debugger, dafür bietet er einen guten Einblick in die aktuell dargestellten und geladenen Objekte.

Anwendung

Um den Debugger nutzen zu können muss zuerst die entsprechende AIR Anwendung installiert werden. Daraus kann über File->Export Client Class die Client Klasse exportiert werden, die dann in das Flash / Flex Projekt eingebunden werden muss.

Beispiel Flash

package {
	import flash.display.Sprite;
	import nl.demonsters.debugger.MonsterDebugger;

	public class Main extends Sprite {

		// Variable to hold the debugger
		private var debugger:MonsterDebugger;

		public function Main() {

			// Init the debugger
			debugger = new MonsterDebugger(this);

			// Send a simple trace
			MonsterDebugger.trace(this, "Hello World!")
		}
	}
}

Beispiel Flex

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init()">
	<mx:Script>
		<![CDATA[

		// Import the debugger
		import nl.demonsters.debugger.MonsterDebugger;

		// Variable to hold the debugger
		private var debugger:MonsterDebugger;

		private function onInit():void
		{
			// Init the debugger
			debugger = new MonsterDebugger(this);

			// Send a simple trace
			MonsterDebugger.trace(this, "Hello World!");
		}
		]]>
	</mx:Script>
</mx:Application>

Fazit

Der De MonsterDebugger ersetzt nicht den Debugger des Flex Builders, aber gerade um komplexere Objekte zu tracen ist er gut geeignet. Der größte Vorteil ist, dass sich Anwendungen in ihrer wirklichen Umgebung (also im Netz, oder als AIR Anwendung) einfach und komfortabel Inspizieren lassen.

Weitere Informationen und Download unter http://www.demonsterdebugger.com/

Text Layout Framework für Flash, Flex und AIR

Das neue Text Layout Framework für den Adobe® Flash® Player 10 and Adobe AIR® 1.5 ist als Beta Version bei Adobe Labs verfügbar. Das Framework setzt auf die neue Text-Engine des Flash Player 10 auf und kann ab Flash CS4 und dem Flex SDK 3.2 benutzt werden. In der nächsten Version von Flex (Codename „Gumbo“) ist das Framework bereits integriert.

Features

Die wichtigesten Features sind:

  • Verschiedene Textrichtungen: links-rechts, rechts-links sowie vertikal
  • über 30 verschiedene Schriftsysteme unter anderen Arabisch, Hebräisch, Chinesisch, Japansich, Koreanisch, Thailändisch, Laotisch und die wichtigesten Systeme von Indien.
  • Verschiedene text styling Optionen wie Ligaturen, Kerning, Leading, Hoch- und Tiefgestellter Text ect.
  • Mehrspaltigkeit
  • Verknüpfte Text Container
  • Tabulatoren
  • Inline Bilder die sich wie Buchstaben im Textfluss verhalten.

Architektur

Der interne Aufbau des Text Layout Frameworks lehnt sich an das Model-View-Controller (MVC) Entwurfsmuster an.

Im Model wird ein abstrakter TextFlow definiert der den Text selbst enthält. Der Text über eine an XHTML angelehnte Struktur hierarchisch gegliedert. Als Basis dient immer eine Instanz der TextFlow Klasse, diese kann direkt einen Absatz (p) enthalten oder einen Container (div). Das DivElement kann wiederum ein DivElement oder einen Absatz enthalten. Der Absatz kann eine SpanElement (Span), eine Grafik (Graphic), ein Link (Link) oder ein TCYElement enthalten. Ein TCYElement repräsentiert kurze Textabschnitte die sowohl horizontal als auch vertikal ausgerichtete Texte enthalten können. Das TCYElement kann ein oder mehrere Span Elemente enthalten.
Außerdem gehört eine Konvertierungsklasse zum Model die Text importieren und wieder exportieren kann.

Im View wird der Text mit Hilfe der neuen Text-Engine des Flash Player 10 gerendert und angezeigt. Für das rendern gibt es zwei Ansätze, einen einfacheren für statischen Text und einen aufwendigeren für dynamischen Text der auch bearbeitet werden kann (siehe Beispiel).

Der Controller des Text Layout Frameworks enthält Klassen um Interaktionen des Benutzers mit dem Text und dessen Formatierung zu realisieren.

Beispiel für das Einbinden von des Text Layout Frameworks in Flex:

<mx:Script>
<![CDATA[
import flashx.textLayout.edit.UndoManager;
import flashx.textLayout.edit.EditManager;
import flashx.textLayout.container.DisplayObjectContainerController;
import flashx.textLayout.container.IContainerController;
import flashx.textLayout.conversion.TextFilter;
import flashx.textLayout.elements.TextFlow;

// container to hold the text
private var _container:Sprite = null;

private function init() : void {

// create a sprite to hold the TextLines
_container = new Sprite();
textContainer.rawChildren.addChild(_container);

// The text to display in the textContainer
var markup:String = ‚<TextFlow xmlns=“http://ns.adobe.com/textLayout/2008″><p><span>Hello,</span> <span     fontWeight=“bold“>World</span></p></TextFlow>‘;

// import the text into a new textFlow
var myFlow:TextFlow = TextFilter.importToFlow(markup, TextFilter.TEXT_LAYOUT_FORMAT);
// create a controller instace
var contr:IContainerController = new DisplayObjectContainerController(_container, textContainer.width,     textContainer.height);
// associate the controller with the flowComposer property of the text flow
myFlow.flowComposer.addController(contr);

// create a new instace of the EditManager and assign it with the interactionManager of the flow
myFlow.interactionManager = new EditManager(new UndoManager());

// update the display list
myFlow.flowComposer.updateAllContainers();
}

]]>
</mx:Script>

<mx:Canvas id=“textContainer“ width=“100″ height=“50″ backgroundColor=“0xFFFFFF“ top=“20″ left=“20″/>

Das war ein kurzer Einblick in das neue Text Layout Framework. Weitere Informationen gibt’s bei Adobe unter http://labs.adobe.com/technologies/textlayout/#fma

Reduzieren der Dateigröße eines Flex-SWFs

Flex-SWFs wachsen gerade bei komplexen Anwendungen oft zu relative großen Dateien an. Größen über 2 MegaByte sind keine Seltenheit. Daraus resultieren größere Ladezeiten für den User und die Gefahr, dass dieser, wenn diese Zeit zu lang wird, den Download abbricht und die Seite und deren Inhalt nie ansehen wird. Jedoch gibt es einige Einstellungen für den Compiler und Möglichkeiten der geladenen Asstes zu reduzieren.

Fangen wir zunächst mit den Compilereinstellungen an:

mxmlc -optimize=true MyApp.mxml
Dieser Ausdruck weist den Compiler an die Dateigröße zu optimieren, indem redundanter Bytecode entfernt wird.

mxmlc -debug=false MyApp.mxml
Durch diese Einstellung werden alle Zeilennummern oder Navigationsinformationen aus dem SWF entfernt, die eigentlich nur während der Entwicklung notwendig sind. Auch dieser Schritt reduziert die Dateigröße um einen großen Schritt.

mxmlc -strict=true MyApp.mxml
Hier verifiziert der Compiler alle Definitionen und Packages innerhalb der import-Statements. Werden Klassen nicht benötigt wirft der Compiler einen Fehler und die Klassen können entfernt werden. Des weiteren wird somit während des compilierens eine Typprüfung durchgeführt, was die Dateigröße wiederum etwas reduziert.

mxmlc -link-report=true MyApp.mxml
Diese Einstellung erstellt eine Zusammenfassung im XML-Format welche Verlinkungen verwendet werden. Somit lässt sich untersuchen welche Verknüpfungen vorhanden sind und daraus schließen ob diese auch wirklich benötigt werden. Während der Codeentwicklung ist es üblich Referenzen auf Klassen zu erstellen, die dann später doch nicht verwendet werden. Diese können mit dieser Zusammenfassung erkannt und entfernt werden.

Auch im Code lassen sich Vorkehrungen treffen um die Dateigröße zu reduzieren. Eine davon ist die Typprüfung mit der getQualifiedClassName() Methode. Prüft man zu Laufzeit ab ob ein Child zum Beispiel ein Button ist wird dies mit einen is-Vergleich durchgeführt.
var isAButton:Boolean = child is mx.controls.Button;
Durch diese Anweisung wird der Compiler dazu gebracht die Buttonklasse in das SWF zu integrieren, auch wenn diese gar nicht benötigt wird. Mit der getQualifiedClassName()-Methode lässt sich der selbe Vergleich bewerkstelligen, ohne jedoch die Vergleichsklasse zu laden.
Die Methode liefert einen String zurück, welche mit dem Namen einer Klasse verglichen werden kann.
var className:String = getQualifiedClassName(child);
var isAButton:Boolean = className == "mx.controls::Button";

Des weiteren muss man überlegen ob wirklich alle Assets von Anfang an in die Anwendung geladen werden müssen, oder nicht doch zur Laufzeit hinzugefügt werden. Dies lässt dich über die Modularisierung des Projektes, run-time stylesheets, RSLs oder eben über das Laden der Assets zur Laufzeit und nicht über das Einbetten dieser, bewerkstelligen. Jedoch ist hier zu überlegen, ob wirklich immer eine Ersparnis vorliegt, denn letztendlich müssen die Daten sowieso geladen werden, die Frage ist wann. Auf jeden Fall ist mit dieser Methode das SWF kleiner und wird schneller geladen.

Ein großer Teil der Größe einer Anwendung sind immer die verwendeten Schriften. Ein komplett eingebetteter Zeichensatz kann mehrere tausend Zeichen enthalten, auch solche die garantiert nie verwendet werden. Entwickler die aus der Flash-Ecke kommen, kennen die Möglichkeit die eingebetteten Zeichen zu reduzieren. Genau dies lässt sich auch im CSS der Applikation umsetzen. Hier wird über den @font-face die Schrift eingebettet. Über das Attribut unicodeRange lässt sich nun bestimmen welche Zeichen der Schriftart zur Anwendung hinzugefügt werden.
@font-face {
src:url("../assets/MyriadWebPro.ttf");
fontFamily: myFontFamily;
unicodeRange:
U+0041-U+005A, /* Upper-Case [A..Z] */
U+0061-U+007A, /* Lower-Case a-z */
U+0030-U+0039, /* Numbers [0..9] */
U+002E-U+002E; /* Period [.] */
}

Ein weiterer Punkt wo die eingebetteten Zeichen bestimmt werden können ist die flex-config.xml, mittels dem <language-range> Tag.
<language-range>
<lang>Latin I</lang>
<range>U+0020,U+00A1-U+00FF,U+2000-U+206F,U+20A0-U+20CF,U+2100-U+2183</range>
</language-range>

Durch diese Einstellungen lässt sich doch einiges an der Dateigröße des SWF machen und letztendlich viele der unnötig geladenen Daten herausfiltern.