Arkiv for juni 2008

Wordle - Tagclouds på den fede måde!

fredag, 20. juni 2008

Disclaimer: Denne artikel omhandler et projekt lavet i Java :-S

Siden tagclouds første gang dukkede op, så har de været en sjov og til dels nyttig måde at vise de mest populære emner i en blog, på et forum og så videre.
En ting som de dog ikke har været, inklusiv min egen omFlash tagcloud, er visuelt smukke.

Men, med fremkomsten af Wordle, så kan det være at det så småt vil begynde at ændre sig, i hvert fald er der her stor inspiration til en meget flottede måde at gøre det på.
Wordle er nemlig, helt kort fortalt, en tagcloud-generator, hvor man selv kan vælge font, farvetema m.m. og så bruger den en algoritme til at placere alle ordene på en visuelt flot måde.
Og her står de ikke bare på linie, nej, små ord kan sagtens være inde i store bogstaver fra andre ord, og der alignes ikke kun på baggrund af bogstavernes firkantede yderlinier, men i forhold til hvert enkelt kurve.

Jeg lavede et output af mine tags fra omFlash og smed ind, og resultatet kan ser her:
Word - omFlash tags

Herefter brugte jeg print-funktionen til at outputte en pdf (hvilket alle på Macs eller folk på PC med Acrobat installeret kan) og den har jeg så igen haft igennem Photoshop for at lave de to nedenstående wallpapers.
Klik for at se den store version, og brug dem hvis du kan li’ dem:

omFlash wallpaper 01
omFlash wallpaper 01

omFlash wallpaper 02
omFlash wallpaper 02

Og nu vil jeg så ellers læne mig godt tilbage i stolen og vente i spænding på hvornår en eller anden for lavet en lignende algoritme til Flash :-)

iPhone med Flash Player? Håbet er lysegrønt!

onsdag, 18. juni 2008

I et konferencekald for aktieanalytikere vedr. Adobes finiansielle resultater for 2. kvartal 2008 kom det frem at:
“With respect to the iPhone, we are working on it. We have a version that’s working on the emulation. This is still on the computer and you know, we have to continue to move it from a test environment onto the device and continue to make it work.”

Og det er udtalt af ingen ringere end CEO Shantanu Narayen, så det tegner godt, omend det absolut ikke er til at vide om den er klar om en måned eller om et år, men mon ikke det bliver er sted midt imellem.

Hele samtalen kan læses her:
Adobe F2Q08 (Qtr End 5/30/08) Earnings Call Transcript

Og jeg fandt den via EricD

Tutorial: Komplet site med dynamisk indhold og SwfAddress - del 3

tirsdag, 17. juni 2008

Menuen er lavet, men nu skal der til at ske noget når man klikker på den, så derfor er det tid til at tage hul på den del af sitet som har med SwfAddress at gøre.

Som det første, er det derfor nu tid til at downloade SwfAddress, hvilket kan ske herfra:
http://www.asual.com/swfaddress/

Efter du har udpakket zip-filen, så finder du de filer som skal bruges til denne tutorial finder i mappen:
Samples\CS3

Herfra skal du kopiere de to mapper swfobject og swfaddress, såvel som filerne SWFAddress.as og SWFAddressEvent.as, og de skal placeres i samme mappe som din fla-fil.
Det kunne se nogenlunde sådan her ud:

Mappestruktur

Det første der skal til, er at vi udvider den funktion der kaldes når man klikker på en knap til, udover blot at trace et id, også at kalde en funktion fra SwfAddress:

function menuClick(_e:Event):void {
	trace(_e.currentTarget.menuid);
	SWFAddress.setValue(menuItems[_e.currentTarget.menuid].address);
}

setValue funktionen bruges til at ændre url’en, hvis sites url eksempelvis er www.mitsite.dk og du kalder funktionen med værdien produkter, så vil url’en ændre sig til www.mitsite.dk/#/produkter/

SwfAddress har en event der holder øje med ændringer i url’en, og det er den event man skal fange for så at loade det rigtige indhold når url’en skifter, den event hedder SWFAddressEvent.CHANGE.

Det er en lidt større funktion, så her kommer først koden og nedenunder forklaringen:

var idPrevious:Number;
var idCurrent:Number;
var idLoading:Number;

const SITE_LABEL:String = "Mit site - ";
function handleSWFAddress(_e:SWFAddressEvent) {
	//try {
		trace("swfaddress: " + _e.value);
		var _address = _e.value.split("/");
		if(_address.length > 2) {
			for(var _i = 0; _i < menuItems.length; _i++) {
				if(menuItems[_i].address == _address[1]) {
					idCurrent = _i;
					break;
				}
			}
		} else {
			idCurrent = 0;
		}
		trace("id: " + idCurrent);
		SWFAddress.setTitle(SITE_LABEL + menuItems[idCurrent].label);
		contentLoad(idCurrent);
	/*
	} catch(err) {
		trace("swfaddress error");
	}
	*/

}
SWFAddress.addEventListener(SWFAddressEvent.CHANGE, handleSWFAddress);

De 3 første variabler bruges til at holde styr på hvilken side der blev vist før (idPrevious), hvilken side der vises nu (idCurrent) og hvilken side der er igang med at blive loadet (idLoading).

Dernæst er der en konstant der hedder SITE_LABEL, og den bruger jeg til når titlen på siden ændres. Hvis man eksempelvis er kommet ind på produktsiden, så skal siden title helst ikke kun være “Produkter”, men derimod “Mit site - Produkter”. Det giver et langt bedre overblik når man har mange tabs åbne, og derudover er det også den tekst der vil være default hvis man laver et bogmærke.

Så kommer selve funktionen der kaldes når url’en ændrer sig, og her er det vigtigt at bemærke en ting:
I eksemplet er der en try/catch som jeg har udkommenteret, og det er den fordi, at når man udvikler er det rarest at se den præcise fejl der måtte blive genereret, fremfor en “pæn” fejlmeddelelse man selv har lavet.
Til gengæld bør man overveje at lave en pæn fejlmeddelelse til når sitet i sidste ende går live, sådan så det opfører sig fornuftigt overfor brugerne - men nok om det.

Sammen med eventen får man en value, som er den del af url’en der kommer efter # og den skal så parses for at finde den korrekte side.
Der er tusind måder at parse strenge på, i eksemplet har jeg valgt den allermest simple, nemlig at splitte ved / og så loope igennem arrayet, men har man et større site er det også en oplagt mullighed at bruge Regular Expressions.

Den værdi der sammenlignes med url’en er address, som er den 2. værdi fra dette kald (som er beskrevet nærmere i del 2):

menuItemAdd("Kontakt os","kontakt-os","kontakt.swf");

Som det sidste, inden det korrekte indhold loades, så ændres titlen med funktionen setTitle, jævnfør det jeg skrev længere oppe.

Og, det var sådan set det!
Der er en række andre funktioner i sitet, men de er mere almindelige og har intet med SwfAddress at gøre, så dem vil jeg ikke gå ind i, men blot opfordre dig til at downloade det komplette site med fla-filer und alles.

Se den komplette demo af sitet her:
Site med SwfAddress (Bemærk det lækre design ;-) )

Og filen med det komplette eksempel kan nappes her:
site_med_swfaddress.zip

Håber det kunne bruges, og spørgsmål er som altid velkomne.

ThunderBolt AS3 - Lidt mere end bare trace

mandag, 16. juni 2008

Jo større og mere kompliceret end applikation bliver, jo mere savner man en måde at vise fejl og andet godt på, som er lidt mere avanceret end den sædvanlige trace.

Et rigtig godt bud i den henseende er ThunderBolt AS3, som er en klasse der blandt andet arbejder sammen med Firebug, til at vise beskeder.
Den har niveauer som info, debug, warning og error, der både i Firebug og den medfølgende AS3 Console bliver farvekodet så de er nemme at skelne fra hinanden.

Som en anden ting kan man også blot inputte et objekt, hvorefter ThunderBolt viser alle værdier på objektet.

Du kan læse meget mere om ThunderBolt her:
10 tips and tricks using ThunderBolt AS3

Og den officielle side, blandt andet med download, findes her:
ThunderBolt AS3

InteractivePNG - Shape test på PNG med transparens

fredag, 13. juni 2008

PNG’er er gode til rigtigt mange ting, men en ting som har hidtil har begrænset deres anvendelighed er muligheden for at shape-teste på dem.
Med andre ord, hvis man har en cirkel som man gemmer som PNG, så har man kun kunnet hittestet på den firkantede PNG, men sådan er det ikke længere!

Moses Gunesch (manden bag FuseKit) har nemlig lavet en ny klasse der hedder InteractivePNG, hvor man selv kan stille hvilket niveau af transparens der skal være i et område for at det tæller med når man hittester.
Hvor god performance er, og om den derfor kan bruges til spil m.m., melder historien ikke noget om endnu, men uanset er det en rigtig nyttig klasse.

Læs mere om og download den her:
InteractivePNG

Oldschool Flash animation

onsdag, 11. juni 2008

Beklager at næste del i serien om SwfAddress lader vente på sig, men det afsnit er lidt større end de andre.

Imellemtiden så vil jeg anbefale at tage et kig på denne artikel:
Animating a Personal Flash Epic

I alt det her virvar af ActionScript 3, klasser, 3d libraries og jeg skal gi’ dig skal jeg, så glemmer man nogen gange helt hvor Flash egentlig kommer fra, og hvor det også er stærkt, nemlig til klassisk animation.

Og ja, programmering kan nu engang ikke gøre det hele, så læs artiklen og bliv inspireret :-)

Eco Zoo - Sådan kan Papervision også bruges

fredag, 6. juni 2008

Papervision har været ude et stykke tid og man har efterhånden set et utal af sider der flipper, objekter der er placeret på en kube og meget andet godt.

The Eco Zoo er også lavet i Papervision, men her er det blevet brugt til at lave et simpelt, men hyggeligt 3D miljø fyldt med en masse små subtile effekter, og ja, så er det også brugt rigtig kreativt, eksempelvis i den foldeud-bog som screenshottet her viser:

The Eco Zoo

Alt i alt kan det virkelig anbefales at tage et kig på:
The Eco Zoo

God weekend!

Tutorial: Eksport af video fra Flash CS3

torsdag, 5. juni 2008

Man har de sidste mange versioner af Flash haft mulighed for at eksportere til video, men problemet har været at det ikke har fungeret ret godt, medmindre der var tale om helt simpel timeline animation.

I Flash CS3 er video-eksporteren heldigvis blevet væsentligt bedre, så den nu også tager højde for ActionScript og giver mulighed for at neste animation, så nu var det på tide med en lille, hurtig gennemgang af hvordan man gør.

Hvad skal vi eksportere?
For at have noget at eksportere, som tester de nye muligheder, så har jeg lavet en fla-fil med følgende:
- En stage på 1920×1080 - kan man have andet i disse HD-tider?
- En Pacman-figur der bevæges frem og tilbage via ActionScript, men som indeholder nestet timeline animation der åbner og lukker munden.
- En cirkel med en gradient, der har en nestet timeline animation som stiller på alphaen. Denne cirkel er så kopieret ud et antal gange og skaleret samt er blevet tintet for at ændre farven.

Fla-en indeholder absolut ingen hokus pokus, men for en god ordens skyld så kan den alligevel hentes her:
video_export.fla

Eksport
For at eksportere til video, så skal man gå ind i File -> Export -> Export Movie

Her er det første man bliver præsenteret for valg af filformat.
Der er en del forskellige formater på listen, men hvis du ønsker adgang til den nye funktionalitet, så er det vigtigt at du vælger Quicktime (*.mov).

Når du har gjort det kommer følgende dialogboks:

Quicktime Export Settings

Det nye er her primært, at man under “Stop exporting” kan vælge “After time elapsed”, hvilket gør at man kan bede om en eksport der har en bestemt længde, og i det tidsrum så optager Flash, billed for billed, en video.

Det fungerer rigtig godt, der er kun én ting man skal være opmærksom på:
Hvis din swf hakker når du tester animationen, så vil den eksporterede video komme til at hakke tilsvarende.
Med andre ord, så kan man ikke bruge det til at lave animation som kræver mere CPU, end at den maskine man sidder på kan afvikle det flydende.

Hvis man klikker på “Quicktime settings” (og det gør man), så kommer man hen til denne boks:

Indstilling af film

Og herfra man vælge præcis hvilken egenskaber filmen skal komprimeres med, noget som er meget afgørende for kvaliteten.
Man kan godt vælge at tweake meget på settings herinde for at få det bedste forhold mellem størrelse og kvalitet, men når vi arbejder med video, så gør vi altid det at vi eksporterer i bedst mulige kvalitet fra Flash.

Ved denne korte video har jeg valgt helt ukomprimeret, hvilket får det ene minuts video til at fylde 14,4GB.
Som oftest vælger jeg dog et format med noget komprimering, eksempelvis H.264 sat til “Optimal”, da filerne ellers bliver uhensigtsmæssigt store at arbejde med.

Pointen er dog, at vi aldrig forsøger at lave slutkomprimeringen i Flash, men blot at eksportere den flottest mulige video, der dermed bliver en slags råfilm, som man efterfølgende kan arbejde videre med.

Slutkomprimering
Til den sidste del af komprimeringen findes der et utal af program man kan bruge, selv plejer jeg at bruge Sorenson Squeeze, da det passer godt til mit workflow.
Der er en række standard presets af komprimeringer at vælge imellem, ligesom man kan lave sine egne, og har man brug for at croppe videoens størrelse eller længde kan det gøres med det samme.

Her et screenshot (klik for stor version) hvor jeg laver en flv, mp4 i høj kvalitet med H.264 og en version til iPod i et hug - ligesom at man naturligvis kan tune kvaliteten inden for det samme format hvis man har lyst til det:

Sorenson Squeeze 5 Pro

Slutresultat
Naturligvis skal det meget smukke slutresultat uploades til en online videotjeneste, så det har jeg også gjort:

Håber at det kunnes bruges :-)

ActionScript 3 tips og tricks fra Grant Skinner

torsdag, 5. juni 2008

Grant Skinner har netop offentliggjort sine slides fra en workshop han holdt i slutningen af 2007, og selvom det er et stykke tid siden, så er der stadig en del godt at hente.

Den kommer glimrende ind på forskellene mellem AS2 og AS3, og han kommer generelt rigtig langt omkring på de 167(!) slides, så der skulle både være noget at hente for de fleste:
ActionScript 3 Workshop

Tutorial: Komplet site med dynamisk indhold og SwfAddress - del 2

tirsdag, 3. juni 2008

Med introduktionen overstået er det nu tid til at dykke ned i selve koden af for vores site.

Hvad er det første man har brug for i en menu? I vores tilfælde er det en simpel knap, med en tekst som kan udskiftes alt efter hvilket menu punkt der er tale om.

Derfor har jeg lavet et movieclip med følgende struktur:
- Top-lag med et dynamisk tekstfelt kaldet Label_txt (husk at embedde de nødvendige tegn!).
- Bund-lag med et movieclip kaldet Background_mc, som indeholder en farvet kasse der er baggrund for teksten.

I mit library har jeg herefter sat den til at blive eksporteret til ActionScript med navnet SiteButton:

SiteButton - Properties

Ingen klasser og i Flash
For at gøre denne tutorial så nem at følge som muligt, så er al koden lavet direkte på første frame i Flash og uden brug af underklasser, men skal man igang med et større projekt, så er det naturligvis oplagt at dele det op samt at bruge en ekstern kode-editor som eksempelvis FlashDevelop.

Menuen genereres
Som første skridt i at generere menuen er her først en funktion som samler de nødvendige informationer i et lille objekt som tilføjes til et array, der kommer til at indeholde alle vores menupunkter:

var menuItems:Array = new Array();

function menuItemAdd(_label:String, _address:String, _file:String):void {
	var _temp:Object = new Object();
	_temp.label = _label;
	_temp.address = _address;
	_temp.file = _file;
	menuItems.push(_temp);
}

De værdier som man sender med til funktionen er:
Label: Det som der skal stå på menupunktet, eksempelvis “Forside”.
Address: Det der skal tilføjes til url’en og som bruges i forbindelse med SwfAddress, eksempelvis “forside”.
File: Den fil der skal loades når man klikker på menupunktet, eksempelvis “forside.swf”.

Angående address, så er det værd at bemærke at værdien skal være unik, og da den bruges som url, så er det også bedst at undgå mellemrum og specialtegn.
Et menupunkt som hedder “Vores øl” kan derfor med fordel have address-værdien “vores-oel”.

Det site som vi laver i denne tutorial har 4 menupunkter, og derfor kaldes funktionen 4 gange:

menuItemAdd("Forside","forside","forside.swf");
menuItemAdd("Produkter","produkter","produkter.swf");
menuItemAdd("Profil","profil","profil.swf");
menuItemAdd("Kontakt os","kontakt-os","kontakt.swf");

Menuen vises
Nu har vi et array med alle vores menupunkter, og ved hjælp af det er det nu tid til at lave og vise selve menuen.

For at gøre det simpelt at ændre placeringen på menuen, er der først et par konstanter:

const MENU_X:Number = 10;
const MENU_Y:Number = 10;
const MENU_PADDING:Number = 10;

X og Y er startplaceringen for det første menupunkt, mens padding er mellemrummet mellem de forskellige menupunkter.

Her så selve funktionen som laver menuen:

function menuCreate():void {
	for(var _i = 0; _i < menuItems.length; _i++) {
		var _temp:SiteButton = new SiteButton();
		_temp.Label_txt.text = menuItems[_i].label;
		_temp.menuid = _i;
		_temp.x = MENU_X + (_temp.width * _i) + (MENU_PADDING * _i);
		_temp.y = MENU_Y;
		_temp.mouseChildren = false;
		_temp.buttonMode = true;
		_temp.useHandCursor = true;
		_temp.addEventListener(MouseEvent.CLICK, menuClick);
		addChild(_temp);
	}
}

Den looper vores array igennem, og for hvert objekt, så indsætter den en ny SiteButton, hvor teksten på Label_txt sættes.
Menuid refererer til knappens position i arrayet, sådan så knappen senere kan finde tilbage til det objekt den er lavet udfra.

mouseChildren = false fortæller Flash at objekter inde i SiteButton ikke kan interagere med musen, mens buttomMode og useHandCursor fortæller Flash at menupunktet skal opføre sig som en knap og at hånden skal vises ved mouseOver.

Hvis du compiler koden nu, så kommer der en fejl, for i denne funktion tilføjer vi også en eventListener, der lytter efter hvornår der klikkes på menupunktet, men den funktion den refererer til er jo ikke defineret endnu.
Den kommer til gengæld her:

function menuClick(_e:Event):void {
	trace(_e.currentTarget.menuid);
}

I først omgang er alt som denne funktion gør, at trace menuid’et, så vi kan se hvilken knap der er blevet klikket på.

Hvis du nu kører al koden, og såfremt du er en ligeså god designer som mig *host*, så vil burde du ende med et resultat nogenlunde i stil med det her:

Step 2

Og den samlede kode, efter lidt restrukturering, kunne se sådan her ud:

//////////////// MENU
const MENU_X:Number = 10;
const MENU_Y:Number = 10;
const MENU_PADDING:Number = 10;

var menuItems:Array = new Array();

menuItemAdd("Forside","forside","forside.swf");
menuItemAdd("Produkter","produkter","produkter.swf");
menuItemAdd("Profil","profil","profil.swf");
menuItemAdd("Kontakt os","kontakt-os","kontakt.swf");

menuCreate();

function menuItemAdd(_label:String, _address:String, _file:String):void {
	var _temp:Object = new Object();
	_temp.label = _label;
	_temp.address = _address;
	_temp.file = _file;
	menuItems.push(_temp);
}

function menuCreate():void {
	for(var _i = 0; _i < menuItems.length; _i++) {
		var _temp:SiteButton = new SiteButton();
		_temp.Label_txt.text = menuItems[_i].label;
		_temp.menuid = _i;
		_temp.x = MENU_X + (_temp.width * _i) + (MENU_PADDING * _i);
		_temp.y = MENU_Y;
		_temp.mouseChildren = false;
		_temp.buttonMode = true;
		_temp.useHandCursor = true;
		_temp.addEventListener(MouseEvent.CLICK, menuClick);
		addChild(_temp);
	}
}

function menuClick(_e:Event):void {
	trace(_e.currentTarget.menuid);
}

Nu har vi noget der ligner en menu, som man endda kan klikke på!

I næste del får vi ting til at ske når der bliver klikket :-)