Sonntag, 31. März 2013

Html5 Canvas - Element um Mittelpunkt rotieren

Vielleicht habt ihr schon mal die Funktion "rotate" im 2d Kontext des Canvas Elements bemerkt.
Bei erster Verwendung scheint das Ergebnis ziemlich seltsam zu sein:


<!DOCTYPE html>

<head>
    
</head>
<body>
    
    <canvas id ="Game", width="300", height="200"></canvas>

    <script>

        var canvas = document.getElementById("Game");
        var ctx = canvas.getContext("2d");

        setInterval(update, 1000 / 60);

        function update() {
            ctx.fillStyle = "#000000";
            ctx.fillRect(0, 0, canvas.width, canvas.height);

            ctx.rotate(0.1);

            ctx.fillStyle = "#ff0000";
            ctx.fillRect(40, 40, 20, 20);
        }

    </script>

</body>
</html>

Dies liegt daran, dass die Funktion "rotate" immer um den Ursprung (0,0) rotiert.
Wir müssen folglich alles so verschieben, dass die Mitte des Rechtecks genau oben links ist.
Danach führen wir die Rotation aus und verschieben alles zurück. Jetzt wird das Rechteck gezeichnet.
Nun müssen wir alles nochmal machen, mit negativer Rotation, um alles wieder zurückzusetzen.
Ich würde folgendes Schema empfehlen:


<!DOCTYPE html>

<head>
    
</head>
<body>
    
    <canvas id ="Game", width="300", height="200"></canvas>

    <script>

        var canvas = document.getElementById("Game");
        var ctx = canvas.getContext("2d");

        var rot = 0;

        var x = 40;
        var y = 40;
        var w = 20;
        var h = 20;


        setInterval(update, 1000 / 60);

        function update() {


            ctx.fillStyle = "#000000";
            ctx.fillRect(0, 0, canvas.width, canvas.height);

            rot += 0.01;

            beginDraw(rot);
            ctx.fillStyle = "#00ff00";
            ctx.fillRect(x, y, w, h);
            endDraw(rot);
           
        }

        function beginDraw(r) {
            ctx.translate(x + w / 2, y + h / 2);
            ctx.rotate(r);
            ctx.translate(-(x + w / 2), -(y + h / 2));
        }

        function endDraw(r) {
            ctx.translate(x + w / 2, y + h / 2);
            ctx.rotate(-r);
            ctx.translate(-(x + w / 2), -(y + h / 2));
        }

    </script>

</body>
</html>