2016-02-23 1 views
1

J'utilise le canevas HTML pour dessiner plusieurs carrés. J'ai 2 fonctions: 1) dessiner un carré et 2) dessiner plusieurs carrés à l'intérieur d'une boucle.Comment utiliser requestAnimationFrame pour animer plusieurs carrés dans une boucle

Maintenant, je veux animer ces carrés en utilisant requestAnimationFrame pour dessiner ces carrés un à la fois. Comment puis-je atteindre cet objectif. Voici un jsFiddle

var canvas = document.getElementById('canvas'), 
     ctx = canvas.getContext('2d'); 

    function rect(x, y, w, h) { 
     ctx.beginPath(); 
     ctx.rect(x, y, w, h); 
     ctx.stroke(); 
    } 

    function drawRect(number, size) { 
     for (var i = 0; i <= number; i++) { 
     rect(i * size, i * size, (i * size) * 2, (i * size) * 2); 
     } 
    } 

    drawRect(10, 5); 

Répondre

0

Vous pouvez faire quelque chose comme

var numRects = 10; 
var size = 5; 
var i = 1;       // which rectangle we're drawing 
var delay = 1000/60;    // num miliseconds between frames 
var before = new Date().getTime(), // last draw time in ms 
    now;       // current time in ms 

function animateRect() { 
    // get the current time to find if we should draw 
    now = new Date().getTime(); 

    // if sufficient time passed since last draw, draw a rect 
    if (now - before > delay && i <= numRects) { 
    rect(i * size, i * size, (i * size) * 2, (i * size) * 2); 
    i++; 
    before = now; 
    } 

    requestAnimFrame(animateRect); 
} 

Edit:

Comme Blindman67 a souligné ci-dessous, requestAnimFrame passe l'horodatage en cours depuis le début de l'animation à la rappeler. Voici comment en profiter:

var numRects = 10; 
var size = 5; 
var i = 1;       // which rectangle we're drawing 
var delay = 1000/60;    // num miliseconds between frames 
var before;       // last draw time in ms 

function animateRect(now) { 
    if (!before) before = now; 
    // if sufficient time passed since last draw, draw a rect 
    if (now - before > delay && i <= numRects) { 
     rect(i * size, i * size, (i * size) * 2, (i * size) * 2); 
     i++; 
     before = now; 
    } 

    requestAnimFrame(animateRect); 
} 

Cependant, cela nécessiterait la modification de la cale l'OP utilise, pour passer l'horodatage en cours à la fonction de rappel dans setTimeout:

window.requestAnimFrame = (function() { 
    return window.requestAnimationFrame || 
     window.webkitRequestAnimationFrame || 
     window.mozRequestAnimationFrame || 
     window.oRequestAnimationFrame || 
     window.msRequestAnimationFrame || 
     function(/* function */ callback, /* DOMElement */ element) { 
      window.setTimeout(callback, 1000/60, new Date.now()); 
     }; 
    })(); 
+1

C'est exactement ce que je veux atteindre. Merci! – kayee

+0

De rien! – Stiliyan

+0

@kayee Je viens de réaliser que j'avais oublié de mettre à jour le temps de tirage «avant» à chaque tirage. Vous devrez ajouter la ligne 'before = now;' au corps de la condition. Voir mon édition pour plus de détails. – Stiliyan

1

J'ai fourni un limiteur de frame et tween pour vous montrer différentes façons d'animer. Le limiteur de trame a les étapes dans votre exemple et l'interpolation a autant d'étapes qu'il faut pour terminer dans un laps de temps donné.

var canvas = document.getElementById('canvas'), 
 
    ctx = canvas.getContext('2d'); 
 

 
//requestAnim shim layer by Paul Irish 
 
//http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/ 
 
window.requestAnimFrame = (function() { 
 
    return window.requestAnimationFrame || 
 
    window.webkitRequestAnimationFrame || 
 
    window.mozRequestAnimationFrame || 
 
    window.oRequestAnimationFrame || 
 
    window.msRequestAnimationFrame || 
 
    function(/* function */ callback, /* DOMElement */ element) { 
 
     window.setTimeout(callback, 1000/60); 
 
    }; 
 
})(); 
 

 
function rect(x, y, w, h, color) { 
 
    ctx.beginPath(); 
 
    ctx.strokeStyle = color; 
 
    ctx.rect(x, y, w, h); 
 
    ctx.stroke(); 
 
} 
 

 
function drawRect(i, size, color) { 
 
    //for (var i = 0; i <= number; i++) { 
 
    rect(i * size, i * size, (i * size) * 2, (i * size) * 2, color); 
 
    //} 
 
} 
 

 
var i = 0; 
 
var incr = 1; 
 
var i_max = 10; 
 
var size = 5; 
 
var fps = 10; 
 
var delay = 1000/fps; 
 
var lastFrame = 0; 
 

 
var animationTime = 5000 
 
var tweenStep = i_max/((animationTime/1000) * 60); 
 
var j = 0; 
 

 
function animateRect() { 
 

 
    // draw at 60fps 
 
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); 
 
    drawRect(i, size, "#0000FF"); 
 
    
 
    // This is a frame limiter. 
 
    var currentFrame = Date.now(); 
 
    
 
    if ((currentFrame - lastFrame) >= delay) { 
 
    i += incr; 
 
    if (i >= i_max) i = i_max - 2, incr = -1; 
 
    if (i < 0) i = 1, incr = 1; 
 
    lastFrame = currentFrame; 
 
    } 
 
    
 
    // this is a tween. The step is calculated for the desired time. 
 
    drawRect(j, size, "#FF0000"); 
 
    j += tweenStep; 
 
    if (j >= i_max) tweenStep *= -1,j=i_max-1; 
 
    if (j < 0) tweenStep *= -1, j=0; 
 
    
 

 
    requestAnimFrame(animateRect); 
 
    //draw rectangle one by one here... 
 
} 
 

 
animateRect(); 
 
//drawRect(10, 5);
<canvas id="canvas" width="600" height="600"></canvas>

+0

Merci pour ça. L'est parfait. – kayee