kenef
kenef

Reputation: 183

setTimeout() not working in animation function | Animation not working

I'm trying to build a very simple animation function. I'm using this tutorial to build my project:

https://www.youtube.com/watch?v=hUCT4b4wa-8

The result after the button is clicked should be a green box moving across the page from left to right. When the button is clicked, nothing happens and I don't get any console errors.

Here's my fiddle: https://jsfiddle.net/xkhpmrtu/7/

And here's a snippet of my code:

<!DOCTYPE html>

<head>

    <meta charset="utf-8" />

    <style type="text/css">

        canvas {
            border: 1px solid #666;
        }

    </style>

    <script type="application/javascript" language="javascript">
        function anim(x,y) {
            var canvas = document.getElementById('canvas');//reference to canvas element on page
            var ctx = canvas.getContext('2d');//establish a 2d context for the canvas element
            ctx.save();//save canvas state if required (not required for the tutoriral anaimation, but doesn't hurt the script so it stays for now)
            ctx.clearRect(0, 0, 550, 400);//clears the canvas for redrawing the scene.
            ctx.fillStyle = "rgba(0,200,0,1)";//coloring the rectangle
            ctx.fillRect = (x, 20, 50, 50);//drawing the rectangle
            ctx.restore();//this restores the canvas to it's original state when we saved it on (at the time) line 18
            x += 5; //increment the x position by some numeric value
            var loopTimer = setTimeout('draw('+x+','+y+')', 2000);// setTimeout is a function that 
    </script>

</head>

<body>

    <button onclick="animate(0,0)">Draw</button>

    <canvas id="canvas" width="550" height="400"></canvas>

</body>

Any idea what I'm doing wrong?

Upvotes: 0

Views: 574

Answers (1)

Blindman67
Blindman67

Reputation: 54041

I just had a look at the tutorial link. I will give if a major thumbs down as it demonstrates how not to animate and how not to do many other things in Javascript.

First the script tag and what is wrong with it

// type and language default to the correct setting for javascrip
// <script type="application/javascript" language="javascript">
<script>

    function anim(x,y) {
        // get the canvas once. Getting the canvas for each frame of an
        // animation will slow everything down. Same for ctx though will not
        // create as much of a slowdown it is not needed for each frame
        // var canvas = document.getElementById('canvas');
        // var ctx = canvas.getContext('2d');
        // Dont use save unless you have to. It is not ok to add it if not needed
        // ctx.save();
        // dont use literal values, canvas may change size
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.fillStyle = "rgba(0,200,0,1)";
        // this line is wrong should be ctx.fillRect(x, 20, 50, 50). It is correct in the video               
        ctx.fillRect = (x, 20, 50, 50);//drawing the rectangle
        // restore not needed
        //ctx.restore();

        x += 5; //increment the x position by some numeric value
        // creating a string for a timer is bad. It invokes the parser and is slooowwwwww... 
        // For animations you should avoid setTimeout altogether and use
        // requestAnimationFrame
        // var loopTimer = setTimeout('draw('+x+','+y+')', 2000);
        requestAnimationFrame(draw);
     // you were missing the closing curly.
     }
</script>

There is lots more wrong with the tut. It can be excused due to it being near 5 years old. You should look for more up todate tutorials as 5 years is forever in computer technology.

Here is how to do it correctly.

// This script should be at the bottom of the page just befor the closing body tag
// If not you need to use the onload event to start the script.


// define a function that starts the animation
function startAnimation() {
    animating = true; // flag we are now animating
    x = 10;
    y = 10;
    // animation will start at next frame or restart at next frame if already running
}
  // define the animation function

function anim() {
  if (animating) { // only draw if animating
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "red"; //coloring the rectangle
    ctx.fillRect(x, y, 50, 50); //drawing the rectangle
    x += xSpeed;

  }
  // set animation timer for next frame
  requestAnimationFrame(anim);
}


// add a click listener to the start button. It calls the supplied function every time you click the button
startAnimButton.addEventListener("click", startAnimation);

const ctx = canvas.getContext('2d'); // get the 2d rendering context

// set up global variables to do the animation
var x, y, animating;
animating = false; // flag we are not animating

const xSpeed = 50 / 60; // Speed is 50 pixels per second at 60fps
                        // dont slow the animation down via frame rate
                        // slow it down by reducing speed.
                        // You only slow frame rate if the machine
                        // can not handle the load.

// start the animation loop
requestAnimationFrame(anim);
canvas {
  border: 1px solid #666;
}
<!-- don't add events inline -->
<button id="startAnimButton">Draw</button>
<canvas id="canvas" width="512" height="128"></canvas>

Upvotes: 1

Related Questions