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

Starten von Systemprozessen in AIR 2.0

Eine der Neuerungen von AIR 2.0 ist die NativeProcess API, die es ermöglicht mit Systemprozessen zu interagieren und somit Systemanwendungen zu starten und zu beenden. Diese API bietet eine Menge von neuen Möglichkeiten für AIR-Applikationen. In diesem Blogeintrag werde ich zeigen wie aus AIR Firefox gestartet werden kann.

Native Installers
AIR Applikationen können nicht nur als *.air Dateien exportiert und weitergegeben werden, sondern auch als „Native Installer“ also *.exe für Windows bzw. *.dmg für MacOS. Dies ist die Voraussetzung um mit Systemprozessen kommunizieren zu können. Ein weiterer Vorteil von Native Installers ist, dass die AIR Runtime mit der Applikation installiert wird, falls diese noch nicht auf dem System des Benutzers verfügbar ist und eine Internetverbindung besteht. Falls der Benutzer nicht mir dem Internet verbunden ist, kommt wenigstens eine Meldung man solle sich doch bitte die aktuelle AIR runtime von der Adobe Seite herunterladen. Weiterhin gibt es die Möglichkeit die AIR Runtime zum Beispiel auf einer CD/DVD mitzuliefern, dafür ist allerdings eine Re-Destributable Lizenz von Adobe nötig, siehe Blogeintrag von Mike Chambers.

Erstellen eines Native Installers
Da man aus FlashBuilder standardmäßig nur *.air Files exportieren kann müssen hier auf die Konsole zurückgreifen. Das Packagingprogramm hierfür heißt ADT und befindet sich im bin Ordner des AIR sdks. Es gibt grundsätzlich zwei verschiedene Arten Native Installers zu erstellen:

  • aus dem Sourcecode eines AIR Projekts
  • aus einer bereits bestehenden AIR Datei

Dieser Aufruf erstellt eine Anwendung mit Native Installer für MacOS aus den Quelldaten der Applikation.

adt -package -storetype pkcs12 -keystore myCert.pfx -target native myApp.dmg main-app.xml main.swf

Folgender Aufruf erstellt eine Anwendung mit Native Installer für MacOS aus einer AIR Datei

adt -package -target native myApp.dmg myApp.air

Um einen Native Installer für Windows zu erstellen wird einfach anstatt myApp.dmg myApp.exe verwendet. Einschränkung: Native Installers können immer nur für das Betriebssystem erstellt werden das gerade genutzt wird. Will mal also ein *.exe für Windows erstellen muss ADT unter Windows aufgerufen werden.

Mehr Infos dazu auf der Adobe Hilfe.

NativeProcess API
Die NativeProcess Klasse bietet die Möglichkeit mit einem Systemprozess zu interagieren. Über die Funktionen start(info:NativeProcessStartupInfo):void und exit(force:Boolean = false):void werden Prozesse gestartet und beendet. Über die Eigenschaften running, standardError, standardInput und standardOutput kann der Prozess überwacht werden.

Der Funktion start() wird eine NativeProcessStartupInfo Objekt übergeben das Informationen zum Prozess enthält der gestartet werden soll. Die Eigenschaft executable muss eine Referenz auf die Datei enthalten die gestartet werden soll und über arguments kann eine Vector von Strings
mit Parametern angegeben werden.

var file = new File('/Applications/Firefox.app/Contents/MacOS/firefox-bin');
var nativeProcessStartupInfo:NativeProcessStartupInfo = new NativeProcessStartupInfo();
nativeProcessStartupInfo.executable = file;
var process:NativeProcess = new NativeProcess();
process.start(nativeProcessStartupInfo);

Dies ist nur ein kleines Beispiel das natürlich beliebig erweiter werden kann. Schön ist auf jeden Fall, dass sich dadurch ganz neue Möglichkeiten für AIR Applikationen auftun. Der große Nachteil von AIR bleibt aber weiterhin, dass die AIR Runtime auf jeden Fall installiert werden muss, es ist also zum Beispiel kein Starten von CD möglich.

Links und weitere Beispiele:

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/

Multitouch in Flash und AIR

Seit dem 02. Februar ist Adobe AIR 2.0 beta 2 unter Adobe Labs verfügbar und bereits seit Mitte Dezember 2009 gibt es eine Betaversion des FlashPlayers 10.1. Eine der Neuerungen ist die Unterstützung von Multitouch Events. Dies eröffnet neue Wege der Interaktion und bringt ein ganz neue Benutzererfahrung die schon von dem IPhone bzw. IPodTouch bekannt ist.

Die Voraussetzung ist natürlich eine entsprechende Hardware. Um die Multitouchfähigkeit testen zu können ist entweder ein multitouchfähiger Touchscreen oder ein Touchpad wie zum Beispiel beim MacBook Pro erforderlich. Außerdem kommt es darauf an wie viele Touchpunkte das Eingabegerät unterstützt, von Flash Seite gib es hier keine Einschränkungen.

Doch wie sieht das Ganze in ActionScript aus? Die Multitouchfähigkeit basiert hauptsächlich auf folgenden Events

  • flash.events.TouchEvent
  • flash.events.GestureEvent
  • flash.events.TransformGestureEvent

Multitouch Input Mode
Es gibt zwei Multitouch Modi MultitouchInputMode.TOUCH_POINT und MultitouchInputMode.GESTURE. Um Multitouch Events verwenden zu können, muss die statische Variable inputMode der Multitouch Klasse gesetzt werden: Multitouch.inputMode = MultitouchInputMode.GESTURE;. Wird der Modus „touchPoint“ gewählt werden TouchEvents dispatched, wird der modus „gesture“ gewählt werden GestureEvents und TransformGestureEvents dispatched. Anhand der TouchPoint Events können die verschiedenen Berührungspunkte ausgelesen und verarbeitet werden.
In diesem Eintrag will ich aber auf die Gestures eingehen. Es werden die vom IPhone bekannten Gesten für zoomen, drehen und wischen (mit zwei oder drei Fingern) und der tab mit zwei Fingern unterstützt.

  • TransformGestureEvent.GESTURE_ZOOM
  • TransformGestureEvent.GESTURE_ROTATE
  • TransformGestureEvent.GESTURE_PAN (2 Finger)
  • TransformGestureEvent.GESTURE_SWIPE (3 Finger)
  • GestureEvent.GESTURE_TWO_FINGER_TAP

Test Anwendung
Um die Funktionen zu testen habe ich eine einfach AIR Anwendung gemacht in der Bild über die Gesures gedreht, gezoomt, und bewegt werden kann. Mein Test AIR App kann hier heruntergeladen werden, es wird allerdings die AIR 2.0beta Runtime benötigt und natürlich ein Eingabegerät das Multitouch unterstützt.

Anwendung auf Propeller
Mein Kollege Alex hat gestern einen Beitrag zu seinem Propeller-Experiment geschrieben, diesen habe ich genommen und mit Multitouchfähigkeiten ausgestattet. Über die Geste Rotation kann der Propeller rotiert werden, über zoom kann gezoomt werden und das Wischen mit 3 Fingern wechelt die Farbe. Hier gibts die AIR Applikation, viel Spaß beim ausprobieren.

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

Schriften für die neue Text Engine des Flash Player 10 einbetten

Eines der Dinge die mir in der Vergangeheit am meisten Zeit und Nerven gekostet haben im Bezug auf Flex und Flash war die Darstellung von Text. Vor allem wenn das Screendesign wieder mal eine Schrift vorgesehen hat, die keine Systemschrift war. Und selbst dann musste die Schrift eingebettet werden um Anti-Aliasing, Rotation oder Alpha darauf anwenden zu können. Das alles soll sich nun mit der neuen Text Engine des Flash Player 10 ändern. Schauen wir uns das mal genauer an.

Seit Flash CS4, dem Flex SDK 3.2 und AIR 1.5 kann schon das neue Flash Text Layout Framework (TLF) verwendet werden, siehe mein Beitrag von 3. April. Dieses benutzt die Text Engine des Flash Players 10.
Die neuen Spark Komponenten in Flex 4 (Codename Gumbo) (siehe Beitrag von Artur) benutzen auch schon diese neuen Funktionalität.

Doch jetzt zum eigenlichen Thema, das einbetten von Schriften: Wie schon gesagt, müssen Systemschriften nicht mehr eingebettet werden um Anti-Aliasing, Rotation oder Alpha verwenden zu können. Aber wenn eine Schrift verwendet werden soll, von der nicht auszugehen ist, dass sie bei jedem der Benutzer auf dem Rechner installiert ist, muss diese natürlich nach wie vor ins swf eingebettet werden.
Es gibt nun zwei Arten Schriften einzubetten: Um Schriften für die „alten“ Halo-Komponenten verwenden zu können muss die alte Art und Weise „DefineFont3“ verwendet werden. „DefineFont4“ heißt die neuen Methode, die für Schriften verwendet werden muss die im Text Layout Framwork oder in den neuen Spark-Komponenten benutzt werden sollen.

Beispiel

<fx:Style>

	@namespace s "library://ns.adobe.com/flex/spark";
	@namespace mx "library://ns.adobe.com/flex/halo";

	/* Einbetten für Halo Komponenten im DefineFont3 Format.
	    Heir ist alles wie gehabt */
	@font-face {
		src: url("arial.ttf");
		fontFamily: "ArialDF3";
	}

	/* Einbetten für Spak Komponenten und TLF im DefineFont4 Format.
	    Hier muss cff auf true gesetzt werden */
	@font-face {
		src: url("arial.tff");
		fontFamily: "ArialDF4";
		cff: true;
	}

	/* Das DataGrid wurde in Flex 4 (Beta) nicht überarbeitet
	    es ist also noch eine alte Halo Komponente und
	    braucht deswegen die Schrift im DefineFont3 Format */
	mx|DataGrid {
		fontFamily: "ArialDF3";
	}

	/* Das Texteingabefeld wurde für Flex 4 überarbeitet
	    ist also nun eine Spark Komponente und braucht deshalb
	    die Schrift im DefineFont4 Format */
	s|TextInput {
		fontFamily: "ArialDF4";
	}

</fx:Style>

Eingebettete Schriften im Text Layout Framwok verwenden

Um die eingebetteten Schriften im TLF zu verwenden müssen diese erstens im DefineFont4 Format eingebettet werden und zweitens muss bei dem verwendeten CharacterFormat „fontLookup“ sowie „renderingMode“ auf „cff“ gesetzt sein:

var cf:CharacterFormat = new CharacterFormat();
cf.fontFamily = "ArialDF4";
cf.fontLookup = FontLookup.EMBEDDED_CFF;
cf.renderingMode = flash.text.engine.RenderingMode.CFF;
textFlow.characterFormat = cf;
textFlow.flowComposer.updateAllContainers();

Fazit

Es ist wie so oft, einiges wird besser, doch eine Neuerung macht nicht alles perfekt. Wird nämlich die gleiche Schrift für Spark und auch Halo Komponenten verwendet, muss sie zweimal eingebettet werden was zu größeren SWFs führt. Adobe ist wohl gerade dabei dafür eine Lösung zu finden, es ist ja noch Zeit bis zum endgültigen Release von Flex 4.
Beim Einbetten von Schriften ist es aber grundsätzlich sinnvon den UnicodeRange auf die Zeichen zu begrenzen die benötigt werden. (siehe Beitrag von Alex)
Eine andere Möglichkeit ist die Schriften zur Laufzeit zu laden (siehe mein Beitrag von 24. Juli)

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.