HTML5 canvas with JavaScript and Flash Player performance

This post is an examination of the performance provided by JavaScript and the canvas HTML element, and its role on mobile platforms in the future. The inspiration for this post came when I stumpled on Water Ripple Canvas by Almer Thies. It was running without problems (with Canvas: 20fps and Water: 30 fps) on my computer but was frighteningly slow with a max of 0.5 fps on my iPhone 4 (yep. A half frame per second!). I therefore found it relevant to produce a comparable piece of code that could run on the canvas element and easily port to Flash, so I could get an idea of how well each technology performed.
It is not a secret that I’m fond of the Adobe Flash Player, and have always believed that Apples excommunication of the player due performance issues had no standing ground, in light of the present alternatives. But HTML5 is a promising technology, that takes the job as website maker seriously again, and that may result in Flash being able to focus on it plug-in nature again, and help lift sites up above the tomorrows standard sites. The most important topic to discuss is: what should happen when our mobile visits a website in the month/years to come. Not distinguishing  between mobile and desktop would lead to sluggish performance on mobiles when canvas gets integrated in eager designers creative solutions – a future that I predict as the “big dip”, in the worst cases.

Study 1

The test case is the famous snowflake that are loved or hated by everyone. The effect is exclusively produced by code and can be scaled easily to increase the load on the processor. I found an example at http://blog.webreakstuff.com/2010/11/building-a-canvas-snowglobe/ by Pedro Freitas. The code can be found on GitHub via https://gist.github.com/716215. I would also use an FPS counter, which could easily be ported to ActionScript and chose snippet from http://stackoverflow.com/questions/4787431/check-fps-in-js
I need it to produce a working example of the FPS counter that can be found at http://eksempler.hjaelpmignu.dk/flash/actionscript/snowflake/snowcanvas.html. I have come to the following data (max is set to 100 FPS):
  • Desktop PC: 99.9 FPS (Firefox)
  • MacBook Pro: 97 - 98 FPS (Safari)
  • iPad (iOS 4.3): 19 - 20 FPS (updated 17/3 – 2011)
  • HTC Desire HD (2.2): 15.5 - 16.5 FPS
  • Inspire 4G (2.3): ~ 14 FPS (updated 17/3 – 2011)
  • HTC Desire (2.2): 14.4 - 14.7 FPS
  • iPad 1 (iOS 4.3): 13 – 13.5 FPS (updated 17/3 – 2011)
  • iPad 1 (iOS 4.2): 12.4 - 13.3 FPS
  • iPhone 4 (iOS 4.3): 9.9 - 10.5 FPS (updated 17/3 – 2011)
  • iPhone 4 (iOS 4.2): 9.9 - 10.3 FPS
  • iPhone 3GS (iOS 4.2): 9.9 - 10.3 FPS
  • HTC Legend: 7.5 - 8.9 FPS
Thanks to @seb_ly and @leebrimelow for additional test results
When I dropped the restriction the PC actually easily spun on over 200 FPS, but the intention here is not to benchmark in the high end, but find a relationship in the “low end” and a relative measurement to a standard machine. PC as well as Mac differ so much on hardware as well as range of browsers, it will not contribute anything positive to uncover all facets.

Conclusion 1

It is evident that both computers frame rates hits the ceiling. The portable Mac has thrown a frame or two in the test, but will probably do 100 FPS in a another run, or with another browser. Of course it cannot run from a Quadro graphics card, but it’s clearly capable of running the test. iOS machines (iPad 1, iPhone 3GS and iPhone 4) has a hard time, to produce frames for the canvas element. On average, they just over 10 FPS.
Desire HD is a bit higher. Not much, but still enough that it should be designated as a better settlement. Lowest is the HTC Legend, with around 8 fps.

Study 2

The second test was made to compare performance between javascripts work on the canvas, and Flash Player’s work with the BitmapData class. The technique used for both are very similar and it will give the best basis for comparison, and minimal editing of the code. You can see an example at http://eksempler.hjaelpmignu.dk/flash/actionscript/snowflake/snowFLA.html
The following changes have been made from the original code:
  • Snow flakes was made as a separate class (Flake.as)
  • Updated variables, etc so they are strictly typed
  • Minor changes in variable names
  • Used Flash Player’s flash.sensors.Accelerometer to handle motion

Flake.as

 

package 
{ 
import flash.display.Sprite; 
import flash.display.BitmapData; 

public class Flake extends Sprite 
{ 
private var canvasWidth; 
private var canvasHeight; 
private var speed: Number; 
private var alpha: Number; 
private var size: Number; 
private var amp: Number; 
private var shift: Number; 
private var range: Number; 

public function Flake (w, h, a, s) 
{ 
this.canvasWidth = w; 
this.canvasHeight = h; 
this.x = 200; 
this.y = Math.random () * -1 * h; 
this.alfa = Math.random () * 0.5 + a; 
this.speed = Math.random (); 
this.size = s - this.speed - this.alfa; 
this.amp = Math.random () * 2; 
this.shift = Math.random () * 25 + 25; 
if (Math.random ()> 0.5) 
{ 
this.shift *= -1; 
} 
this.drift = Math.random () - 0.5; 
draw (); 
} 
public function draw (canvas: BitmapData = null): void 
{ 
this.graphics.beginFill (0xFFFFFF, this.alfa); 
this.graphics.drawCircle (0.0, this.size); 
this.graphics.endFill (); 
} 
public function move (f, wind): void 
{ 
this.y + = this.speed; 
this.x + = Math.cos (f / this.shift) * this.amp + + this.drift wind; 
if (this.y> this.canvasHeight) 
{ 
this.restart (); 
} 
} 
public function restart (): void 
{ 
this.y = -20; 
this.shift = Math.random () * 25 + 25; 
this.x = 200; 
} 
} 
}

 

 

MainApp.as

package
{ 
import flash.display.Sprite; 
import flash.display.Bitmap; 
import flash.display.BitmapData; 
import flash.utils.Timer; 
import flash.events.TimerEvent; 
import flash.geom.Rectangle; 
import flash.geom.Matrix; 
import flashx.textLayout.elements.InlineGraphicElement; 
import flash.sensors.Accelerometer; 
import flash.events.AccelerometerEvent; 
import flash.text.TextField; 

public class MainApp extends Sprite 
{ 
private var bgflakes: Array = new Array (); 
private var fgflakes: Array = new Array (); 
private var bgFlakeCount: int = 200; 
private var fgFlakeCount: int = 50; 
private var frame count: int = 0; 
private var wind: int = 0; 
private var dWidth: int; 
private var dHeight: int; 
private var orientX: int = 1; 

private var bgBitmapData: BitmapData; 
private var bgCanvas: Bitmap; 
private var fgBitmapData: BitmapData; 
private var fgCanvas: Bitmap; 
private var timer: Timer; 
private var orientation: Boolean = false; 
private var myAcc: Accelerometer; 

private var filter Strength: int = 20; 
private var frame hours: int = 0; 
private var loading loop: Date = new Date (); 
private var this loop: Date = new Date (); 

private var fps: TextField; 

public function MainApp () 
{ 
init (); 
} 

private function init () 
{ 
dWidth = this.stage.stageWidth; 
dHeight = this.stage.stageHeight; 
bgBitmapData = new BitmapData (dWidth, dHeight, false, 0x000000); 
bgCanvas = new Bitmap (bgBitmapData); 
fgBitmapData = new BitmapData (dWidth, dHeight, true, 0xFF0000); 
fgCanvas = new Bitmap (fgBitmapData); 
addChild (bgCanvas); 
addChild (fgCanvas); 

fps = new TextField (); 
addChild (fps); 
fps.textColor = 0xFFFFFF; 

was i = 0; 
for (i = 0; i { 
bgflakes.push (New Flake (bgCanvas.width, bgCanvas.height, 0,3)); 
} 
for (i = 0; i { 
fgflakes.push (New Flake (fgCanvas.width, fgCanvas.height, 0.2,4)); 
} 
hours = new Timer (10); 
timer.addEventListener (TimerEvent.TIMER, draw); 
timer.start (); 

if (Accelerometer.isSupported) 
{ 
orientation = true; 
myAcc = new Accelerometer (); 
myAcc.addEventListener (AccelerometerEvent.UPDATE, onAccUpdate); 
} 
} 

private function onAccUpdate (e: AccelerometerEvent): void 
{ 
orientX = e.accelerationX; 
} 

private function setWind () 
{ 
if (! orientation) 
{ 
was mx: Number = mouseX - dWidth / 2; 
wind = (mx / dWidth) * 3; 
} 
lodging 
{ 
Wind = Number (orientX) * 3; 
} 
if (! wind) 
{ 
wind = 0; 
} 
} 

private function draw (e: Event hours) 
{ 
frame count + = 1; 

bgBitmapData.fillRect (new Rectangle (0.0, dWidth, dHeight), 0x000000); 
fgBitmapData = new BitmapData (dWidth, dHeight, true, 0xFF0000); 
setWind (); 
was: int = 0; 
for (i = 0; i { 
bgflakes [i]. move (frame count, wind); 

bgBitmapData.draw (bgflakes [i], new Matrix (1,0,0,1, bgflakes [i]. x, bgflakes [i]. y)); 
} 
for (i = 0; i { 
fgflakes [i]. move (frame count, wind); 

fgBitmapData.draw (bgflakes [i]); 
} 

was this frame hours: int = (Number (this loop = new Date ())) - Number (last loop); 
Frame hour + = (this frame - time frame hours) / filter strength; 
load loop = this loop; 
fps.text = (1000/frameTime). toFixed (1) + "fps"; 
} 
} 
}

 

Comments on Code
I have kept the draw () inside the Flake class and draw the flakes with graphics.drawCircle () to keep the code across the examples as similar as possible. The transfer of values on canvas size, etc. are also retained in the Flash version is also preserved. Finally, I used Bitmap () and BitmapData () to simulate the properties used on the canvas element.

Results 2

With mobile units, that is capable of running Flash Player 10.1 and canvas, I try to measure them against each other. Not as a battle, favoring one technology, for the future (I think) belongs to them both. It’s more an attempt to find out how bad Flash performs and supporters of the canvas as a “Flash Killer” has some back support. I’ll update as I stumple on different phones/tablets on my way:
  • Dersire HD (2.2): Canvas ~ 16.5 FPS and Flash 10.1 ~ 24.2 FPS
  • Inspire 4G (2.3): Canvas ~ 14 FPS and Flash 10.1 ~ 22 FPS (updated 17/3 – 2011)
  • HTC Desire (2.2): Canvas ~ 14.5 FPS and Flash 10.1 21.7 to 23.5 FPS
You are welcome to submit own measurements

Conclusion

I get a relatively higher frame rate when running the test in Flash Player on Android than if I the canvas version. I wasn’t able to turn the relationship between the numbers on my phone, not even leveling the difference in frame rate. I therefore think that the user will have a better experience of this experiment in a flash player, than with a canvas version. It is important to remember that the canvas element’s ability to deliver, do not need to inflict on the general view on HTML5 and CSS3. My feeling is that CSS3 has a fairly good performance on the mobile devices, perhaps because of their predictable nature, but I haven’t investigated that topic yet.
Finally, I have not taken installed software on the devices into account. It may be relevant in a recount to look at parameters such as:
  • How long the phone has been switched on.
  • Is it connected to the charger.
  • Programs running in the background.
  • Video documentation of test
My point here is to get some numbers up in the air, and a comparison of material playd on mobile devices. Please reply with the results of your own measurements for computer, tablet and mobile.
Links to tests:
Links to documents

HTML5 canvas med JavaScript og Flash Player performance

Dette indlæg er en undersøgelse af den performance som præsteres af henholdsvis JavaScript og Canvas elementet og dets rolle på mobile platforme i fremtiden. Inspirationen fik jeg da jeg kom forbi Almer Thies Water Ripple Canvas der kørte uden problemer (med Canvas: 20fps og Water:30 fps) på min computer men skræmte mig fra vid og sans med et maks på 0.5 fps på min iPhone (yep. En halv frame i sekundet!!). Jeg fik derfor en idé om at finde et sammenligneligt stykke kode, der kunne afvikles fra canvas og nemt porteres til Flash, så jeg kunne danne mig et overblik over hvor godt de hver i sær præsterede.
Selv er jeg tilhænger af Adobe Flash Player og har altid ment at iOS bandlysning af den på grund af performance ikke havde nogen gang på jord, set i lyset af alternativerne. At vi så grundlæggende skal tage os en grundig snak om, hvad der skal ske, når vores mobile enheder besøger en hjemmeside i årene der kommer, er en helt anden snak – en fremtid, som jeg spår som “det store dyk”, i værste tilfælde.

Forsøg 1

Valget faldt på de berømte snefnug, som er elsket/hadet af alle. Effekten bliver udelukkende produceret med kode, og kan skaleres nemt for at øge belastningen. Jeg fandt et eksempel på http://blog.webreakstuff.com/2010/11/building-a-canvas-snowglobe/ af Pedro Freitas. Koden kan findes på Github via https://gist.github.com/716215. Jeg skulle også bruge en FPS-counter, der nemt kunne porteres til ActionScript og valget faldt på kodestumpen fra http://stackoverflow.com/questions/4787431/check-fps-in-js
Jeg har brug det til at producere et virkende eksempel med FPS-counter, der kan findes på http://eksempler.hjaelpmignu.dk/flash/actionscript/snowflake/snowcanvas.html. Jeg er kommet frem til følgende data (max er sat til 100 FPS):
  • Desktop PC: 99.9 FPS (Firefox)
  • MacBook Pro: 97 - 98 FPS (Safari)
  • iPad (iOS 4.3): 19 - 20 FPS (opdateret 17/3 – 2011)
  • HTC Desire HD (2.2): 15.5 - 16.5 FPS
  • Inspire 4G (2.3): ~ 14 FPS (opdateret 17/3 – 2011)
  • HTC Desire (2.2): 14.4 - 14.7 FPS
  • iPad 1 (iOS 4.3): 13 – 13.5 FPS (opdateret 17/3 – 2011)
  • iPad 1 (iOS 4.2): 12.4 - 13.3 FPS
  • iPhone 4 (iOS 4.3): 9.9 - 10.5 FPS (opdateret 17/3 – 2011)
  • iPhone 4 (iOS 4.2): 9.9 - 10.3 FPS
  • iPhone 3GS (iOS 4.2): 9.9 - 10.3 FPS
  • HTC Legend: 7.5 - 8.9 FPS
Tak til @seb_ly og @leebrimelow for yderligere testresultater
Jeg droppede begrænsningen og så at PC’eren faktisk nemt snurrede den over 200 FPS, men meningen her er ikke at benchmarke i den høje ende, men finde et forhold i “den lave ende” og en relativ måling til en standard maskine. PC såvel som Mac varierer så meget på hardware samt udvalg af browsere, at det ikke vil bidrage til noget positivt at afdække alle facetter.

Konklusion

  • Det er klart at fornemme at begge computere rammer toppen. Den bærbare Mac har smidt en frame eller to i testen, men vil sikkert ramme 100 FPS i en anden. Selvfølgelig kan den ikke løbe fra et Quadro grafikkort, men klart er det at der er rigelig overskud til at løse opgaven.
  • iOS maskinerne (iPad 1 og iPhone 4) har en hård tid, med at producere frames til canvas elementet. I gennemsnit ligger de på lidt over 10 FPS.
  • Desire HD ligger en smule højere. Ikke meget, men alligevel nok til at det må betegnes som en bedre afvikling.

Forsøg 2

Forsøg nummer to var lavet for at sammenligne performance mellem JavaScripts arbejde på canvas, samt Flash Playerens arbejde med BitmapData klassen. Teknikken der bruges til begge er meget ens, og det vil give det bedste sammenligningsgrundlag, og mindst mulig redigering i koden. Du kan se et eksempel på http://eksempler.hjaelpmignu.dk/flash/actionscript/snowflake/snowFLA.html
Følgende ændringer er blevet foretaget fra originalkoden:
  • Snefnug lavet som en selvstændig klasse (Flake.as)
  • Har opdateret variabler osv så de er strict typed
  • Mindre ændringer i variabel navne
  • Brugt Flash Playerens flash.sensors.Accelerometer til at håndtere bevægelse
Flake.as

package
{
import flash.display.Sprite;
import flash.display.BitmapData;

public class Flake extends Sprite
{
private var canvasWidth;
private var canvasHeight;
private var speed:Number;
private var alfa:Number;
private var size:Number;
private var amp:Number;
private var shift:Number;
private var drift:Number;

public function Flake(w,h,a,s)
{
this.canvasWidth = w;
this.canvasHeight = h;
this.x = 200;
this.y = Math.random() * -1 * h;
this.alfa = Math.random() * 0.5 + a;
this.speed = Math.random();
this.size = s - this.speed - this.alfa;
this.amp = Math.random() * 2;
this.shift = Math.random() * 25 + 25;
if (Math.random() > 0.5)
{
this.shift *=  -1;
}
this.drift = Math.random() - 0.5;
draw();
}
public function draw(canvas:BitmapData = null):void
{
this.graphics.beginFill(0xFFFFFF,this.alfa);
this.graphics.drawCircle(0,0,this.size);
this.graphics.endFill();
}
public function move(f,wind):void
{
this.y +=  this.speed;
this.x +=  Math.cos(f / this.shift) * this.amp + this.drift + wind;
if (this.y > this.canvasHeight)
{
this.restart();
}
}
public function restart():void
{
this.y = -20;
this.shift = Math.random() * 25 + 25;
this.x = 200;
}
}
}

 

MainApp.as
 

package
{
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.geom.Rectangle;
import flash.geom.Matrix;
import flashx.textLayout.elements.InlineGraphicElement;
import flash.sensors.Accelerometer;
import flash.events.AccelerometerEvent;
import flash.text.TextField;

public class MainApp extends Sprite
{
private var bgflakes:Array = new Array();
private var fgflakes:Array = new Array();
private var bgFlakeCount:int = 200;
private var fgFlakeCount:int = 50;
private var frameCount:int = 0;
private var wind:int = 0;
private var dWidth:int;
private var dHeight:int;
private var orientX:int = 1;

private var bgBitmapData:BitmapData;
private var bgCanvas:Bitmap;
private var fgBitmapData:BitmapData;
private var fgCanvas:Bitmap;
private var timer:Timer;
private var orientation:Boolean = false;
private var myAcc:Accelerometer;

private var filterStrength:int = 20;
private var frameTime:int = 0;
private var lastLoop:Date = new Date();
private var thisLoop:Date = new Date();

private var fps:TextField;

public function MainApp()
{
init();
}

private function init()
{
dWidth = this.stage.stageWidth;
dHeight = this.stage.stageHeight;
bgBitmapData = new BitmapData(dWidth,dHeight,false,0x000000);
bgCanvas = new Bitmap(bgBitmapData);
fgBitmapData = new BitmapData(dWidth,dHeight,true,0xFF0000);
fgCanvas = new Bitmap(fgBitmapData);
addChild(bgCanvas);
addChild(fgCanvas);

fps = new TextField();
addChild(fps);
fps.textColor = 0xFFFFFF;

var i = 0;
for (i=0; i 			{
bgflakes.push(new Flake(bgCanvas.width, bgCanvas.height,0,3));
}
for (i=0; i 			{
fgflakes.push(new Flake(fgCanvas.width, fgCanvas.height,0.2,4));
}
timer = new Timer(10);
timer.addEventListener(TimerEvent.TIMER, draw);
timer.start();

if (Accelerometer.isSupported)
{
orientation = true;
myAcc = new Accelerometer();
myAcc.addEventListener(AccelerometerEvent.UPDATE, onAccUpdate);
}
}

private function onAccUpdate(e:AccelerometerEvent):void
{
orientX = e.accelerationX;
}

private function setWind()
{
if (! orientation)
{
var mx:Number = mouseX - dWidth / 2;
wind = (mx/dWidth)*3;
}
else
{
wind = Number(orientX) * 3;
}
if (! wind)
{
wind = 0;
}
}

private function draw(e:TimerEvent)
{
frameCount +=  1;

bgBitmapData.fillRect(new Rectangle(0,0,dWidth, dHeight),0x000000);
fgBitmapData = new BitmapData(dWidth,dHeight,true,0xFF0000);
setWind();
var i:int = 0;
for (i=0; i 			{
bgflakes[i].move(frameCount, wind);

bgBitmapData.draw(bgflakes[i], new Matrix(1,0,0,1,bgflakes[i].x, bgflakes[i].y));
}
for (i=0; i 			{
fgflakes[i].move(frameCount, wind);

fgBitmapData.draw(bgflakes[i]);
}

var thisFrameTime:int = (Number(thisLoop=new Date())) - Number(lastLoop);
frameTime+= (thisFrameTime - frameTime) / filterStrength;
lastLoop = thisLoop;
fps.text = (1000/frameTime).toFixed(1) + " fps";
}
}
}

 

Kommentarer til koden
Jeg har beholdt draw() inde i Flake klassen og tegner den fysisk op med graphics.drawCircle() for at beholde koden på tværs af eksemplerne. Overførsel af værdier om canvas-størrelse osv. er også bevaret i Flash eksemplet er også bevaret. Endelig er der brugt Bitmap() og BitmapData() til at simulere de egenskaber som bruges på canvas elementet.

Resultat 2

På modeller, hvor der både kan køres Flash Player 10.1 og canvas vil jeg prøve at teste dem op mod hinanden. Ikke så meget en kamp mellem det ene og det andet, for fremtiden (tror jeg) tilhører dem begge, men mere et forsøg på at finde ud af, hvor dårlig Flash præsterer og om tilhængere af canvas, som “Flash Killer” har noget at have det i. Jeg vil opdatere efterhånden som jeg rammer flere forskellige telefoner på min vej:
  • Dersire HD (2.2): Canvas ~ 16.5 FPS og Flash 10.1 ~ 24.2 FPS
  • Inspire 4G (2.3): Canvas ~ 14 FPS og Flash 10.1 ~ 14 FPS (opdateret 17/3 – 2011)
  • HTC Desire (2.2): Canvas ~ 14.5 FPS og Flash 10.1 21.7 to 23.5 FPS
I er velkommen til at indsende oprigtige målinger

Konklusion

Jeg ser en relativ højere frame rate når jeg afvikler i Flash Player på Android, end hvis jeg udfører tilsvarende med canvas elementet. Det er ikke lykkedes mig at vende forholdet mellem tallene på min telefon, end ikke få dem til at nærme sig hinanden, mærkbart. Jeg vil derfor mene at brugeren vil have en bedre oplevelse af dette eksperiment i en Flash Player, end ved en canvas-løsning. Det er vigtigt at huske på, at canvas elementets evne til at præstere, ikke behøver at gå ud over den generelle opfattelse af HTML5 og CSS3. Min fornemmelse er, at CSS3 har en ok afvikling på de mobile enheder, måske på grund af deres forudsigelige natur, men det har jeg stadig tilbage at undersøge.
Endelig har jeg ikke forholdt mig til, hvad der er installeret på enhederne. Det kan være relevant i en fintælling at se på parametre som:
  • Hvor lang tid telefonen har været tændt.
  • Er den tilsluttet oplader.
  • Kører der programmer i baggrunden.
  • Videodokumentation af test
Mit ønske her er at få nogle tal i luften, og et forhold til den relativt ringe afvikling af materiale på mobile enheder.
Meld gerne tilbage med resultater af jeres egne målinger på computer, tablet og mobil.
Links til tests:
Links til dokumenter

Er der en fremtid for Adobe Flash Player når HTML5 sætter sig i sadlen

Der er mange diskussioner om hvordan der skal kommunikeres på Internettet i fremtiden, og mange klumper af mudder flyver fra henholdsvis Flash og HTML lejren, med forsøg på at berettige deres egen eksistens. Når designere og udviklere er så passioneret, som de heldigvis ofte er, kommer klapperne desværre op og de glemmer at zoome lidt ud og se det hele i et større perspektiv. Jeg selv, er jo en Adobe mand af guds nåde og elsker alt, hvad der har med design af interaktive løsninger at gøre, så jeg bliver rendt meget på dørene med spørgsmål som “Er Flash en død sild?”, “Kan man overhovedet noget med HTML?”, “Hvordan er performance?”, “Kan man lave Flash sites uden flash?” osv.

Jeg er selvfølgelig meget optaget af mulighederne på Flash Platformen, fordi det er en platform der byder på et utal af muligheder for at udtrykke sig og det gør det til et spændende udgangspunkt til projekter. Jeg er lige så optaget af HTML platformen og dermed også hele HTML5 “brandet” (inkl. CSS og JavaScript) da det bringer nye muligheder for at layoute oplevelser og kommunikere effektivt direkte i en browser.

Hvad skal Flash til for?

Flash har altid haft til opgave at løse interaktive og dynamiske opgaver, som HTML ikke kunne løfte selv – sådan er livet som plugin. Det gælder ikke bare Flash, men alt fra Quicktime player til video og over til Unitys web player til 3D indhold. HTML har altid været (og vil forhåbentlig altid være) et opmærkningssprog, som kan bruges til at definere indholdet på et website. Det bliver efterfølgende knyttet til et stylesheet, der definerer hvordan det skal se ud i en browser. JavaScript har endelig kunne forholde sig intelligent til brugerens måde at agere og derved variere over eller reagere på dele af indholdet. Der er mange flere facetter, men som grov skitse, går det nok an.

Problemerne er opstået, da Flash har kunnet løfte mange af de layoutmæssige og interaktive muligheder og samtidig været overlegen, uden sammenligning, når det gjaldt at integrere dynamik, animation, lyd, interaktion osv. Det har gjort det nemt for mange at bruge flash som fundament for hele sitet og ikke bare en plugin, der skal løse en opgave på et website. Ulempen ved dette er de navigationsmæssige udfordringer, søgemaskineoptimering og det faktum, at der skal meget til for at erstatte den grundrendering som er givet fra browseren

Der skal være en god bund

Den vigtigste opgave for HTML er at markere indholdet på et site. Du bruger et h-tag til overskriver, img-tag til billede osv. De nye tags i html5 giver øget mulighed for at definere om der er tale om navigation, artiker, video, lyd osv. Dette er et stort fremskridt, da det derved er muligt at forholde sig til den rene information og trække informationer på tværs af sites. Skal jeg bruge indholdet fra en artikel, kan jeg nemt fangle et <article> tag og vide at al relevant infromation bliver flyttet med. Dette vil lette presset på <div> tags (dividers) og gøre at de får arbejdsro til at opdele i forhold til layout og ikke indhold.

Gøgeungen skal væk

En af de største irritationsmomenter ved Flash er, at designere og udviklere har været fristet af de frie layoutmuligheder med Adobe Flash Professional. Følelsen af at kunne styre layoutet 100% uden at tænke på bokse og CSS har gjort at mange sites udelukkende er lavet med Flash. Lige så snart at <body> tag’et er kommet på banen, har dets eneste opgave været at vise én kæmpe swf-fil og absolut intet søgebart html … hvis jeg var html, ville jeg også blive stik tosset.

 Designere skal, endnu mere i fremtiden, lære at bruge det bedste værktøj tilat løse opgaven. Der skal ikke laves Flash-sites fordi det er nemt – der skal laves Flash-sites fordi det er det rigtige at gøre. Hvis en designløsning umiddelbart kan lade sig gøre med html5 og css3 bør og skal den laves med disse teknologier – alt andet vil være et skridt ned at stigen.

Du vil i fremtiden se flere veldesignede html5 løsninger, der løser opgaver og udtrykker sig på samme måde som du er vant til at se produceret med Flash idag.

Hvad med Javascript og canvas

Når snakken er faldet på html5 som en Flash-killer, har de fleste egentlig ment at Javascript, med muligheden for at tilgå <canvas> tag’et har givet browseren et værktøj, der stort set kan løse alle opgaver som Flash har stået for. Jeg vil ikke gå i detaljer med teknikken, men der er en del der skal løses før den metode kommer i nærheden af Flash Playeren. Eksempler som jeg lige kan komme på er:

  • Performance. Der er stor forskel på hvor godt JS afvikles på de forskellige platforme
  • Stabilitet. Der er forskel på hvordan JS afvikles på de enkelte platforme
  • Tilgang til Virtuel Motor. En oversigt på http://en.wikipedia.org/wiki/JavaScript_engine viser, hvor mange forskellige motorer, der findes til browserne
  • Opdateringsgrad. Flash Player’en har mulighed for at opdatere sig jævnligt og implementere nye tiltag. Standarder er ofte årevis om at blive enige
  • Er ikke en plug-in. Fordi Javascript ikke er en plug-in kan du ikke skræddersy din oplevelse på tværs af browsere, men må tilpasse den til målgruppen.

Det er ikke fordi oventstående kun er af det onde, men det er nogle af de faktorer, der gør at der stadig er behov for properitære plug-ins der løfter de umiddelbare behov der stilles, indtil en standard kan defineres – en standard, der ofte er fremkommet efter at enkelte udviklere har præsenteret deres løsning på et problem. F.eks. er WebGL ved at samle sig efter år, men udbrydergrupper og konsollideringer. Det er nu, efter omkring 5 år, ved at nå til et punkt, hvor den kan bruges i nyere browsere (mangler dog stadig Internet Explorer). Der er ikke noget der tyder på at det vil gå hurtigere, når det “næste nye” bliver opfundet, hvilket giver nogle ret lange svartider på spørgsmål om innovation.

Jeg ser dog en stor fremtid i at JavaScript kommer til at servicere HTML5 og sørge for at logikken, der skal præsentere HTML elementerne bliver varetaget. Formvalidering, jQuery bliver fast inventar i fremtiden. Jeg har sværere ved at se Javascript skulle løse opgaver der ikke er bundet til html – ikke fordi det ikke er teknisk muligt, men simpelhen fordi jeg tror det bliver for bøvlet at udvikle og bliver afviklet for dårligt i browseren.

Endelig ser jeg stort set alle reklamer i fremtiden udviklet i HTML/CSS og JavaScript, da det vil give et bredere marked og en bedre integration i forhold til kontekst. Det bliver sværere for ad-blockers i fremtiden at adskille indholdet, og man kunne i sit stille sind have håbet på et <advertisement> tag i specifikationerne (selv om den nok ikke ville blive brugt) :-)

Hvornår kan man bruge det

Selvom de mere skeptiske siger i 2022, er det min klare opfattelse at du skal bruge det, når en overvejende del at brugerne understøtter det. Du skal selvfølgelig være opmærksom på mulighederne for at præsentere indholdet i browsere der ikke understøtter det, men der er ikke nogen grund til at udelade alt det nye, fordi 15% af de besøgende ikke er opdateret (der er typer at sites, der ikke kan være så frimodige) :-)

Hvis du vil have en god oversigt kan du kigge på http://findmebyip.com/litmus der under emner viser en fin gennemgang af alle de nye tags og script-muligheder. Det er også interessant læsning, når du kigger på video og lyd understøttelse i de forskellige browser og mulighederne på Mac og Win … der er stadig lidt, der skal masseres på plads.

Der findes også en oversigt på https://netaverages.adobe.com/en-us/index.html (login med dit Adobe ID) der viser en procentvis dækning af udbredelsen (både desktop og mobile) og give en pegepind for, hvordan mulighederne for implementation er. Det vigtigste at huske på (de næste mange år) er at tilbyde sekundære løsninger til browsere der ikke understøtter de nye selectors.

Kan jeg lære det

Det er ikke et spørgsmål om du kan … du skal. Fremtidens interaktive designer skal være god til både Flash og HTML – en af delene er ikke nok. Der vil i de næste år komme værktøjer der hjælper. Opdateringer af eksisterende programmer som Adobe Dreamweaver 11.0.3 og Adobe Illustrator HTML5 pack er allerede igang med at løfte noget af byrden, og programmer som Edge vil tilbyde helt nye muligheder for at arbejde med HTML5 og de omkringliggende teknologier. Der er allerede en masse sites der giver sig i kast med mulighederne, men et par at starte med kunne være:

Kan jeg få hjælp

Selvfølgelig kan du det. Der er mange sites, hvor artiklerne tillader kommentarer under. De virker flinke til at svare på spørgsmål. Ellers er der altid vores eget Dreamweaver forum. God fornøjelse med HTML5

Næste Flash Player har fokus på 3D

En kort opdatering – eller rettere en teaser for, hvad den næste version af Flash Player’en kommer til at indeholde. Hvis rygterne rundt omkring på nettet taler sandt, og det du kan søge dig frem til står for troende, så vil MAX 2010 give noget særligt, til dem der er interesseret i at udvikle spil eller andre applikationer, der udnytter alle tre dimensioner.

Det hele startede (tror jeg) med at Thibault Imbert, der er Product Manager på Flash Playeren skrev følgende tweet

Hvis du kigger på MAX online kalender under http://max.adobe.com/schedule/by-session/flash-player-3d-future/ae6f2190-c17a-4411-9e20-44a135e340b0 vil du se et indlæg om næste generation af en 3D API. Ordlyden er:

Join Sebastian Marketsmueller, Adobe Flash Player engineer, for a deep dive into the next-generation 3D API coming in a future version of Flash Player. Marketsmueller will unveil exciting new APIs and demos never shown before, including some exclusive content you cannot miss as a Flash Platform developer.

Efterfølgende uddyber Thibault på sin side. Uddyber og uddyber – det er måske så meget sagt. Men han skærper helt sikkert interessen. Andre sites som http://templatereactor.com/blog/3d-api-for-the-flash-player.html fulgte kort efter. Rygterne strækker sig langt, og kommentarfeltet fanger mange af dem – helt til Unity og Flash integration af en slags.

Set i lyset af de nye muligheder for at udvikle applikationer til iPhone med Flash udviklingsværktøjer, bliver det helt sikkert interessant, hvad der diskes op med. En ting er sikkert – der skal også diskes op med nogle hastighedsforbedringer, hvis det rigtig skal rykke :-)

Der er vel ikke andet at sige end: “Glæder mig til slutningen af oktober!” :-)

Adobe Flash CS4 og 30 sekunders timeout i Windows XP (Internet Explorer 7)

Jeg stødte for et par dage siden ind i problemer med at modtage data fra en server. Dataene var lang tid om at blive genereret fra serverens side, da det omfattede en del database kald og generering af XML inden det endelige resultat kunne sendes tilbage til Flash Playeren (en Flash Projector).

Problemet bestod i at den nogle gange kunne modtage data, og andre gange fejlede. Nogle maskiner modtog altid data, og andre havde meget svært ved det – alt sammen med den samme projector fil – arrrrgh.

Efter lang tid søgning inde i Flash, fandt jeg et system i dem der havde sværest ved at modtage, og de var alle opdateret med Internet Explorer 7. Det viser sig at der (med opdateringen til IE7) bliver sat en ny standard værdi for timeout på HTTP-requests. Den er nu gået fra 60 minutter (IE4) over 5 minutter (IE5 og 6) til 30 sekunder (IE7+). Normalt skaber det ikke problemer, men Adobe Flash CS4 bruger systemets internet indstillinger til at tilgå internettet, og den venter ikke så lang tid som browserne gør – de har deres egne indstillinger, der tvinger systemet til at blive ved med at lytte efter svar – det gør Flash CS4 ikke umiddelbart.

Problemet løses ved at sætte en værdi i Registreringsdatabasen kaldet ReceiveTimeout (DWORD) til det antal millisekunder du vil have den skal vente inden den giver op. Vejen ned til væredien er [HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings]

Jeg har optaget et screencast af hvordan du gør, hvis du ikke har arbejdet med registreringseditorer før. Den kan ses på:

http://experts.na3.acrobat.com/p71212063/

God fornøjelse

/ockley