Kom igång med HTML5 – Canvas

Att spela spel på internet genom Silverlight- eller Flash-baserade gränssnitt blir alltmer populärt, vilket man kan se om man är flitig användare av Facebook. Dessa spel kräver att man har rätt komponent installerad för att kunna köra dem över huvud taget. På vissa enheter som till exempel mobiltelefoner händer det ofta att man inte kan installera dessa plugins, och då måste man lösa det på ett annat sätt. Det skulle t.ex. kunna lösas genom att man skriver ett separat program som påminner om det man visade på sidan, men även det kan ge problem då man har flera olika applikationer att underhålla.

För att smidigt få det att fungera på både datorer, mobiltelefoner och andra enheter så skulle man kunna använda Canvas. Canvas är en del av HTML5 och gör det möjligt att rita ut objekt direkt på skärmen med hjälp av nya JavaScript-API:er.

I exemplen så använder jag Internet Explorer 9 som använder hårdvaruaccelerering för att rendera objekten, men alla webbläsare med stöd för Canvas bör klara av detta.

Skapa ett Canvas-objekt

För att få in Canvas på hemsidan så måste vi använda oss utav det nya Canvas-elementet i HTML5.

Jag har en grundsida som ser ut så här:

<!DOCTYPE HTML>
<html>
<head>
    <title>Canvas</title>
    <script>
 
    </script>
    <style>
        body
        {
            background-color: #000;
            text-align: center;
        }
        
        div
        {
            margin: 0px auto;
            width: 400px;
        }
        
        canvas
        {
            background-color: #fff;
        }
    </style>
</head>
<body>
    <div>
        <canvas id="canvas" width="300" height="300">
            Din webbläsare har inte stöd för canvas.
        </canvas>
    </div>
</body>
</html>

Här använder jag den nya doctypen för HTML5 för att visa för webbläsaren att det är det jag vill använda. Sedan har jag lagt in ett Canvas-element som är 300x300 pixlar stort. Om vi öppnar upp det i en webbläsare utan stöd för Canvas så får vi upp texten innanför start- och sluttaggarna.

Om vi öppnar upp det här nu så får vi:

canvas0

Den vita ytan är vår canvas där vi kan börja rita med hjälp av JavaScript. Till att börja med så vill jag få dit en bakgrund som ska skifta mellan vitt och rött.

Jag lägger nu till det här mellan script-elementen:

function init() {
    var c = document.getElementById('canvas');
    var ctx = c.getContext('2d');
 
    var grad = ctx.createLinearGradient(0, 0, 300, 300);
    grad.addColorStop(0, '#FFFFFF');
    grad.addColorStop(0.5, '#FF0000');
    grad.addColorStop(1, '#FFFFFF');
    ctx.fillStyle = grad;
    ctx.fillRect(0, 0, 300, 300);
}

Ser vi på sidan nu så ser vi att vi har fått det här:

canvas1

När man ska rita på en canvas-yta så måste man först få tag i canvas-elementet. Här använder jag document.getElementById, men det går lika bra att använda jQuery för att få rätt element. Nästa steg är att skapa upp en 2d-context, vilket är den enda som finns i HTML5. Det objektet vi får där är det vi ska använda för att rita ut de olika delarna på canvasen.

Nu när vi har ett canvas-element och fått tag i dess 2d-context så kan vi börja rita på den. Det vi vill ha är en gradient som börjar skifta färg längst upp till vänster (0,0) och slutar längst ned till höger (300, 300) i det aktuella LinearGradient-objektet.

Vi sätter sedan färgerna vi vill ha. I början ska det vara vitt, i mitten ska det ha blivit rött, och mot slutet ska det ha gått tillbaka till vitt. Värt att notera är att 0 är början och 1 är slutet.

Till sist så vill vi fylla vårt canvas-element med den gradient vi just skapade. För att göra det så sätter vi fillStyle till ”grad” som är vårt objekt, och anropar sedan fillRect() där vi sätter att vi ska börja rita längst upp till vänster och sluta längst ned till höger.

Det som händer nu är att vi får en bakgrund med skiftande färg direkt på sidan.

Rita ut mönster

Med bara en bakgrundsbild kommer vi dock inte långt, utan på denna kanske vi vill lägga till objekt. Det vi ska göra härnäst är att rita ut en genomskinlig kvadrat med skugga bakom mitt på ytan, och det gör vi på nästan samma sätt som vi ritade ut bakgrunden.

Det vi behöver lägga till efter den tidigare koden är det här:

ctx.shadowOffsetX = 3;
ctx.shadowOffsetY = 3;
ctx.shadowBlur = 5;
ctx.shadowColor = 'rgba(0, 0, 0, 0.7)';
ctx.fillStyle = 'rgba(0, 0, 255, 0.3)';
ctx.fillRect(50, 50, 200, 200);

Vi använder fortfarande det objektet vi hämtade tidigare, men fortsätter att rita vidare på canvasen efter att ha ritat ut bakgrunden.

Först och främst så vill vi sätta skugga på det objektet vi vill rita ut. Jag har satt Offset till 3 på både X och Y vilket ger en 3 px stor skugga. Jag har sedan satt shadowBlur till 5, vilket avgör hur suddigt det ska vara (ju högre siffra desto suddigare skugga). Jag sätter därefter färgen på skuggan till svart, men opacity till 0,7 för att få skuggan lite svagare.

När vi har satt egenskaper för skuggan så ska vi sätta färgen på själva objektet som ska ritas ut. Här använder vi återigen RGBA för att kunna sätta opacitet. Jag väljer att sätta färgen till blå, men med 0.3 i opacitet.

Det sista vi gör är att rita ut objektet på canvasen. Det skall hamna 50px från toppen och vänster, samt vara 200x200px stort.

Kikar vi på sidan nu så kan vi se att vi har fått det här:

canvas2

Med lite JavaScript har vi nu gjort vad som tidigare krävde att vi lade in en bild. Då det är JavaScript så kan vi dessutom göra det här väldigt dynamiskt.

Animera rutan

För att få lite liv i canvasen så kan vi animera innehållet. Då det inte finns någon state för det som ritas ut så får vi hålla reda på det själv. Det vi ska göra här är en väldigt enkel animering där rutan ska flyttas fram och tillbaka mellan två olika positioner med 500 millisekunders mellanrum.

För att göra det enklare att animera så flyttar jag ut koden för att rita ut objektet till en separat funktion. Jag anropar sedan den funktionen när sidan laddas för att få en bild direkt, och anropar den sedan igen var 500:e millisekund. Koden för det blir det här:

var position = 75;
 
function init3() {
    drawImage();
    setInterval(function () { drawImage(); }, 500);
}
 
function drawImage() {
    var c = document.getElementById('canvas');
    var ctx = c.getContext('2d');
 
    var grad = ctx.createLinearGradient(0, 0, 300, 300);
    grad.addColorStop(0, '#FFFFFF');
    grad.addColorStop(0.5, '#FF0000');
    grad.addColorStop(1, '#FFFFFF');
    ctx.fillStyle = grad;
    ctx.fillRect(0, 0, 300, 300);
 
    ctx.shadowOffsetX = 3;
    ctx.shadowOffsetY = 3;
    ctx.shadowBlur = 5;
    ctx.shadowColor = 'rgba(0, 0, 0, 0.7)';
    ctx.fillStyle = 'rgba(0, 0, 255, 0.3)';
    ctx.fillRect(position, position, 200, 200);
 
    position = (position == 25) ? 75 : 25;
}

Det är helt vanlig JavaScript som nu ritar ut ett animerat objekt direkt på skärmen. Det här exemplet är inte särskilt avancerat, men det finns redan nu spel skrivna med Canvas. En bra källa för Canvas-spel är http://www.canvasdemos.com där man kan hitta en mängd spel och program som inte kräver att man har något plugin installerat.

Då Internet Explorer 9 kommer med hårdvaruaccelerering för Canvas så kommer det bli möjligt att skapa väldigt avancerade spel och program som renderas med hjälp av grafikkortet, och det genom att använda HTML5 och JavaScript!

2 Comments

  • Efter att du lagt till Javascriptet "function init()" så behöver man trigga javascriptet med onload="init()" för att den inte ska förbli vit även efter att man lagt till skriptet innanför script-taggarna.

  • Det har du rätt i. Alternativet är att använda t.ex. det här i JavaScriptet:

    if(window.addEventListener) { // IE 9 & övriga webbläsare
    window.addEventListener('load', function() { init(); });
    }
    else { // IE 8 och tidigare versioner av IE
    alert('Din webbläsare har inte stöd för Canvas. Uppgradera till IE 9 eller använd en annan webbläsare för att se sidan korrekt.');
    }

    Då IE 9 är första versionen av IE med stöd för Canvas och addEventListener, samt då alla andra webbläsare har stöd för det så kan man anta att det är en äldre version av IE om else triggas här.

Comments have been disabled for this content.