senäh

17senäh und so…

HTML/CSS/JS
21. Jul 2011
Kommentare: 2

HTML5: Kleiner Performancetest mit dem Canvas-Element

Kategorien: HTML/CSS/JS | 21. Jul 2011 | Kommentare: 2

Willkommen zum #HTML5ExperimentDesTages! 😉 Nach der kleinen Fingerübung gestern mit der Canvas-API wollte ich heute einen kleinen Performancetest machen. Am Ende der Übung war es aber gar nicht mehr die Performance, die für mich interessant war, sondern die Verwendung von JavaScript für den Test. Bisher bin ich mit AS3 eine klassenbasierte objektorientierte Programmierung gewohnt, was bei JavaScript in der Form nicht möglich ist. Durch JavaScript habe ich erfahren, dass man auch ohne Klassen objektorientiert programmieren kann. JavaScript löst das über Prototypen. Das wird eine ziemliche Umstellung… Aber darüber will ich noch gar keine weiteren Worte verlieren, da ich noch nicht genug in der Materie stecke, um schlaue Reden zu halten. Kommen wir also zum eigentlichen Experiment.

Performancetest – Kreise

Ich zeichne mehrere Kreise auf das Canvas-Element. Gestern habe ich euch ja bereits erklärt wie man Kreise mit der Canvas-API zeichnet. Dieses Mal möchte ich die Kreise animieren lassen. Sie sollen zufällig auf dem Canvas platziert werden und sich in eine zufällige Richtung bewegen. Wenn sie auf den Rand des Canvas-Elements stoßen, sollen sie ihre Richtung ändern. Dabei soll die aktuelle fps berechnet werden. Außerdem soll man über ein Eingabefeld die Anzahl der Kreise ändern können. Fertsch!

Vorschau

So soll das Ergebnis aussehen:

Screenshot Canvas-Performancetest

Screenshot Canvas-Performancetest

Und hier der Code:

index.html

<!DOCTYPE html>
<html lang="de">

<!--
You can use this code as you wish,
but please recommend our site http://www.senaeh.de.
@author Philipp Zins/Donald Pipowitch
-->

<head>
    <title>Canvas: Einfacher Performancetest</title>

    <meta charset="UTF-8"/>
    <meta name="description" content="Ein einfacher Performancetest mit dem Canvaselement."/>
    <meta name="keywords" content="HTML5, Canvas"/>
    <meta name="author" content="Philipp Zins/Donald Pipowitch"/>

    <link rel="stylesheet" type="text/css" href="css/style.css"/>

    <script type="text/javascript" src="js/balls/BallManager.js"></script>
</head>

<body onload="init()">

    <!-- canvasBalls -->
    <div>
        <form name="BallForm" onsubmit="return createBalls(document.BallForm.BallCount.value)">
            Neue Anzahl an Kreisen:
            <input type="text" name="BallCount">
            <input type="submit" value="Absenden">
        </form>

        <p id="counterBalls">
            Anzahl: 0
        </p>
        <canvas id="canvasBalls" width="500" height="400">
            Dein Browser unterstützt das Canvas-Element nicht.
        </canvas>
        <p id="FPS">
            <!-- place Stats from Stats.js here -->
        </p>
    </div>

</body>
</html>

style.css 😉

canvas
{
    border: solid 1px #000000;
}

BallManager.js

/**
 * You can use this code as you wish,
 * but please recommend our site http://www.senaeh.de.
 * @author Philipp Zins/Donald Pipowitch
 */

document.write('<script type="text/javascript" src="js/balls/Ball.js"></script>');
document.write('<script type="text/javascript" src="js/com/mrdoob/Stats.js"></script>');

var canvas;
var context;
var width;
var height;

var ballList = new Array();

function init()
{
    // canvas
    canvas = document.getElementById("canvasBalls");
    context = canvas.getContext("2d");
    width = canvas.width;
    height = canvas.height;
    // init balls and loop
    createBalls(100);
    startLoop();
    // stats
    var stats = new Stats();
    document.getElementById("FPS").appendChild(stats.domElement);
    setInterval(function ()
    {
        stats.update();
    }, 1000 / 60);
}

function createBalls(count)
{
    ballList.splice(0, ballList.length);
    for (var i = 0; i < count; i++)
    {
        createBall();
    }
    document.getElementById("counterBalls").innerHTML = "Anzahl: " + ballList.length;
    return false;   // don't reload page
}

function startLoop()
{
    setInterval(draw, 33); // 33 milliseconds = ~ 30 frames per sec
}

function draw()
{

    context.clearRect(0, 0, width, height);
    for (var i = 0; i < ballList.length; i++)
    {
        ballList[i].update(width, height);
        context.fillStyle = "#FF0000";
        context.beginPath();
        context.arc(ballList[i].x, ballList[i].y, ballList[i].radius, 0, Math.PI * 2, true);
        context.closePath();
        context.fill();
    }
}

function createBall()
{
    var randomX = Math.random() * width;
    var randomY = Math.random() * height;
    var ball = new Ball(randomX, randomY);
    ballList.push(ball);
}

Ball.js

/**
 * You can use this code as you wish,
 * but please recommend our site http://www.senaeh.de.
 * @author Philipp Zins/Donald Pipowitch
 */

var Ball = function (x, y)
{
    this.x = x;
    this.y = y;
    this.speedX = Math.random() * 1.5 + 0.5;
    if(Math.random() < 0.5)
        this.speedX *= -1;
    this.speedY = Math.random() * 1.5 + 0.5;
    if(Math.random() < 0.5)
        this.speedY *= -1;
    this.radius = 4;
    this.update = update;
}

function update(width, height)
{
    this.x += this.speedX;
    this.y += this.speedY;
    if ((this.x - this.radius < 0 && this.speedX < 0) ||
            (this.x + this.radius > width && this.speedX > 0))
    {
        this.speedX *= -1;
    }
    if ((this.y - this.radius < 0 && this.speedY < 0) ||
            (this.y + this.radius > height && this.speedY > 0))
    {
        this.speedY *= -1;
    }
}

Stats.js

Die geniale Stats.js von MrDoob zum Anzeigen der fps findet ihr hier. Die JavaScript-Version ist ein Port der AS3-Version.

Ergebnis

Das fertige Ergebnis könnt ihr euch hier im Browser anzeigen lassen.

Fazit

Selbst bei 2000 Kreisen habe ich auf meinem MacBook Pro durchgängig 30 fps. Ich denke dieser Wert ist recht akzeptabel. Auf meinem HTC Desire komme ich auf ca. 28 fps bei 200 Kreisen. Ich bin gespannt, was man da noch herauskitzeln kann.

Autor: Pipo

...kommt ursprünglich aus der Designerecke, ist aber im Laufe seines Studiums in die Webentwicklung gestolpert. Kann sich seit dem nicht so richtig entscheiden wo er hingehört und wagt deswegen vielleicht die Flucht nach vorne in ein komplett neues Gebiet. Vielleicht Management? Niemand weiß es. Auch er nicht.