Tyler330
Tyler330

Reputation: 415

No animation, endless loop in Canvas

I am trying to create what I thought would be a simple Canvas to move a point from A to B using requestAnimationFrame.

http://jsfiddle.net/p1L81yk4/1/

Unfortunately it is not showing anything, and the animation loop seems to be headed towards infinity.

Can anyone explain what I am doing wrong? And is there a flag I can create to show when the animation should stop?

var startX = 10,
startY = 10;
var endX = 200,
endY = 350;

var speed = 1;
var dx = endX - startX;
var dy = endY - startY;
var distance = Math.sqrt(dx * dx + dy * dy);
var moves = distance / speed;
var xunits = (dx / moves);
var yunits = (dy / moves);
var posit = {
    x: startX,
    y: startY 
};


var fps = 60;
var delay = 1000 / 30;

function draw() {
    ctx.clearRect(0, 0, canv.width, canv.height);
    ctx.save();
    ctx.translate(startX, startY);
    ctx.beginPath();
    ctx.arc(0, 0, 5, 0, Math.PI * 2);
    ctx.fill();
    ctx.restore();
}

function move() {
    startX += dx;
    startY += dy;

    console.log(posit);

    if (moves > 0) {
        moves++;
        posit.x += xunits;
        posit.y += yunits;
    }
}

var start = 0;

function animate() {
    running = true;
    var current = new Date().getTime(),
    delta = current - start;

    if (delta >= delay) {
        move();
        draw();
        start = new Date().getTime();
    }

    anim = requestAnimationFrame(animate);
}

animate();

Upvotes: 0

Views: 295

Answers (2)

somethinghere
somethinghere

Reputation: 17330

Using basic trigonometry you can make the entire code look and read easier, with less up front variables. I still need to set quite a lot of variables here, but you would want to mostly calculate them on the fly (which means you would have to move things like angle, from and to value and distance into the myDraw() function).

var myCanvas   = document.getElementById('myCanvas');
var myContext  = myCanvas.getContext('2d');
    myContext.fillStyle = '#000';
// Values expressed as x, y, positions
var fromValue  = [300,20];
var toValue    = [100,100];
// time expressed in Milliseconds
var time       = 5000;
var start      = Date.now();
// Get the angle with the arctangent function
// tan(angle)  = opposite / adjacent => atan(opposite / adjacent) = angle
// atan2 is used because you can pass it the lengths and it takes care of
// some negative edge cases.
var angle      = Math.atan2(toValue[0] - fromValue[0], toValue[1] - fromValue[1]);
// Basic distance because.. Pythagoras. (a^2 = sqrt(b^2 + c^2))
var distance   = Math.sqrt(Math.pow(toValue[0] - fromValue[0], 2) + Math.pow(toValue[1] - fromValue[1], 2));

function myDraw(now){
  
  // The max distance can be divided by the total time, multiplied by the time that has passed
  var t = (distance / time * (now - start));
  var x = fromValue[0] + Math.sin(angle) * t;
  var y = fromValue[1] + Math.cos(angle) * t;
  
  // Clear the canvas by resetting its width
  myCanvas.width = myCanvas.width;
  
  // Draw the arc at position x and y
  myContext.arc(x, y, 3, 0, Math.PI * 2);
  myContext.fill();
  
  // Return false if the animation is done.
  if(now < start + time) return true;
  else return false;
}

function myAnimate(){
  // Keep executing as long as myDraw() returns true
  if(myDraw(Date.now())) window.requestAnimationFrame(myAnimate);
}

myAnimate();
<canvas width="500" height="500" id="myCanvas" />

Upvotes: 1

maowtm
maowtm

Reputation: 2012

  • You should not use save and restore, these functions is for saving and restoring the images.
  • You should translate posit.x and posit.y instead of startX and startY.
  • You are changing startX and startY which is not reasonable.
  • You need a if to determinate if or if not to continue aniamtion.

Which ends up with a working code:

    var canv = document.getElementById('canv'),
        ctx = canv.getContext('2d');
    var startX = 10,
        startY = 10;
    var endX = 200,
        endY = 350;

    var speed = 2;
    var dx = endX - startX;
    var dy = endY - startY;
    var distance = Math.sqrt(dx * dx + dy * dy);
    var moves = distance / speed;
    var xunits = (dx / moves);
    var yunits = (dy / moves);
    var posit = {
        x: startX,
        y: startY
    };


    var fps = 60;
    var delay = 1000 / 60;

    function draw() {
        ctx.clearRect(0, 0, canv.width, canv.height);
        //ctx.save();
        ctx.translate(posit.x, posit.y);
        ctx.beginPath();
        ctx.arc(0, 0, 5, 0, Math.PI * 2);
        ctx.fill();
        ctx.translate(-posit.x, -posit.y);
        //ctx.restore();
    }

    function move() {
        //startX += dx;
        //startY += dy;

        //console.log(posit);

        if (moves > 0) {
            moves++;
            posit.x += xunits;
            posit.y += yunits;
        }

    }

    var start = 0;

    function animate() {
        running = true;
        var current = new Date().getTime(),
            delta = current - start;

        if (delta >= delay) {
            move();
            draw();
            start = new Date().getTime();
        }
        
        if(posit.y < endY)
            anim = requestAnimationFrame(animate);

    }
    animate();
<canvas id="canv" width="500" height="500"></canvas>

Upvotes: 2

Related Questions