mrdwright
mrdwright

Reputation: 3

Combine multiple HTML5 canvas animations

I have this jsfiddle http://jsfiddle.net/t9L6g3bd/4/

// requestAnimationFrame Shim
(function () {
    var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame   || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();


var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 75;
var endPercent = 101;
var curPerc = 0;
var counterClockwise = false;
var circ = Math.PI * 2;
var quart = Math.PI / 2;

context.lineWidth = 2;
context.strokeStyle = '#333';
animate();


function animate(current) {
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.beginPath();
    context.arc(x, y, radius, -(quart), ((circ) * current) - quart, false);
    context.stroke();
    curPerc++;
    if (curPerc < endPercent) {
        requestAnimationFrame(function () {
            animate(curPerc / 100)
        });
    } else {
        ex(126, 126);
        cross(126, 126);
        //fadein(0);
    }
}

function fadein(a) {
    context.lineWidth = 1.5;
    context.globalAlpha = a;
    context.beginPath();
    context.moveTo(166, 84);
    context.lineTo(84, 166);
    context.stroke();
    context.beginPath();
    context.moveTo(166, 166);
    context.lineTo(84, 84);
    context.stroke();
    if (a != 0.8) {
        requestAnimationFrame(function () {
        fadein(a + 0.01);
        });
    }
}

    function ex(x, y) {
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.beginPath();
    context.moveTo(84, x);
    context.lineTo(168, y);
    context.stroke();
    if (x != 168) {
        requestAnimationFrame(function () {
            ex(x + 1, y - 1)
        });
    }
}
function cross(x, y) {
    //    context.clearRect(0, 0, canvas.width, canvas.height);
    context.beginPath();
    context.moveTo(84, x);
    context.lineTo(168, y);
    context.stroke();
    if (x != 84) {
        requestAnimationFrame(function () {
            cross(x - 1, y + 1)
        });
    }

}

I was wondering if there was a way to combine the circle animation and the x at the same time, or one after the other so that they both are on the screen and both have smooth edges

Upvotes: 0

Views: 287

Answers (2)

GameAlchemist
GameAlchemist

Reputation: 19294

You should indeed use only one requestAnimationFrame, because its overhead is quite big, but mainly for the clarity of your code (hard to know as it is which object is animating or not).
-->> What about storing all the animation data into objects, and even letting the object animate / draw themselves ?
This way you have a clear separation of concerns, and changing one aspect of the animation is much easier.
I started to do this in this fiddle :

http://jsfiddle.net/0200h552/6/

the animation loop becomes quite simple :

function animate() {
    requestAnimationFrame(animate);
    context.clearRect(0, 0, canvas.width, canvas.height);
    //
    circle.draw();
    if (!circle.animate()) {
        ex.draw();
        cross.draw();
        ex.animate();
        cross.animate();
    }
}

And here are the three objects in use :

var circle = {
    x: centerX,
    y: centerY,
    radius: 75,
    curPerc: 0,
    endPercent: 101,
    animate: function () {
        if (this.curPerc < this.endPercent) {
            this.curPerc++;
            return true;
        }
        return false;
    },
    draw: function () {
        var perc = this.curPerc / this.endPercent;
        var oldAlpha = context.globalAlpha;
        context.globalAlpha = perc;
        context.beginPath();
        context.arc(this.x, this.y, this.radius, -(quart), ((circ) * perc) - quart, false);
        context.stroke();
        context.globalAlpha = oldAlpha;
    }
};

The "ex" :

var ex = {
    x: centerX,
    y: centerY,
    animate: function () {
        if (this.x != 168) {
            this.x++;
            this.y--;
            return true;
        }
        return false;
    },
    draw: function () {
        var x = this.x;
        var y = this.y;
        context.beginPath();
        context.moveTo(84, x);
        context.lineTo(168, y);
        context.stroke();
    }
};

The cross :

var cross = {
    x: centerX,
    y: centerY,
    animate: function () {
        if (this.x != 84) {
            this.x--;
            this.y++;
            return true;
        }
        return false;
    },
    draw: function () {
        var x = this.x;
        var y = this.y;
        context.beginPath();
        context.moveTo(84, x);
        context.lineTo(168, y);
        context.stroke();
    }
};

Upvotes: 0

Lunster
Lunster

Reputation: 906

You needed to refactor your code.

Link to refactored jsfiddle

function animate() {

    if (curPerc < endPercent) {
            context.clearRect(0, 0, canvas.width, canvas.height);    
            drawCircle(curPerc / 100);
            fadeIn(curPerc / 100);
            curPerc++;
            requestAnimationFrame(function () {
                animate();
            });   
    }
}

Basically you needed to change your code so that only one animation loop is running, and on each loop iteration call an update function for each animation. I would say though, that the code overall is kind of difficult to maintain and you should consider further refactoring to rectify this. Hope this helps.

Upvotes: 1

Related Questions