逐步在画布中绘制线条动画

时间:2014-05-12 07:06:23

标签: javascript jquery html5 animation canvas

所以我想使用requestAnimationFrame在HTML 5画布上绘制一条线的动画。

我已经完成了这个

function animateWrapper(centerX, centerY, xAngle, yAngle, width, height) {
    var request = requestAnimationFrame(animate);
    var canvas = document.getElementById("drawing");
    var context = canvas.getContext('2d');  
    function animate (centerX, centerY, xAngle, width, height) {
        drawLine(centerX,centerY, centerX, centerY - height, context, request);
    }
}

function drawLine(startX, startY, endX, endY, context, request) {
    context.beginPath();
    context.moveTo(startX, startY);
    step += 0.05;
    // if (step > 1) step = 1;
    var newX = startX + (endX - startX) * step;
    var newY = startY + (endY - startY) * step;
    context.lineTo(newX, newY);
    context.stroke();
    if (Math.abs(newX) >= Math.abs(endX) && Math.abs(newY) >= Math.abs(endY)) {
        cancelAnimationFrame(request);
        step = 0;
    }
}

$(document).ready(function(){
    animateWrapper(100, 100, 40, 40, 400, 400);
});

现在,centerY,xAngle,width,height都是未定义的(这是有意义的 - 它们没有被传入)。这会导致endY成为NaN,因此不会发生动画。

我不知道如何解决这个问题 - 如何在请求动画框架中传递这些参数?

2 个答案:

答案 0 :(得分:1)

这应该有效:

function animateWrapper(centerX, centerY, xAngle, yAngle, width, height) {
    function animate () {
        drawLine(centerX,centerY, centerX, centerY - height, context, request);
    }

    var request = requestAnimationFrame(animate);
    var canvas = document.getElementById("drawing");
    var context = canvas.getContext('2d');  
}

您不必使用任何参数调用animate(),因为变量centerXcenterY,...和height在{animate()范围内定义了1}}(即它们当时是已知的,因此您可以在函数内部使用它们。)

此问题的答案列出了变量在JavaScript中可见/可用的各种方式:What is the scope of variables in JavaScript?

答案 1 :(得分:0)

您的代码中存在第一个问题:不会出现动画,因为您只调用一次requestAnimationFrame(rAF)。您可以将rAF视为setTimeout,它将在下一次屏幕可用时触发一次每次都会一次又一次地调用的setInterval。

第二个问题是经典的javascript闭包/绑定/范围问题 因此,首先解决方案是切换到更现代的语言,如google Dart(:-)) 例如,其他解决方案是将您的animate函数绑定到其参数 在javascript中,如果你这样做:

var myBoundFunction = someFunction.bind(null, arg1, arg2, arg3);

然后,调用

myBoundFunction();

与调用:

具有相同的效果
someFunction(arg1, arg2, arg3);

在这里查看更多详细信息,以及第一个参数的使用:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

我可以给你一些关于如何更改代码的提示,但无论如何我猜你想要动画几行,所以你必须改变它的工作方式以使其更灵活。
我强烈建议你去对象并将一条线定义为具有(x,y,...)和绘制和更新方法的对象。

类似的东西(这次使用闭包):

var canvas   = ... ;    // do the DOM access only once
var context  = ... ;   // do the DOM accessd only once      
var myObjectsToDraw = [];

function animate() {
       ... return and stop animation if some condition is met ...
       requestAnimationFrame(animate);
       ... clear screen ..
       // draw all objects
       for (var i in myObjectsToDraw) myObjectsToDraw[i].draw();
       // update all objects
       for (var i in myObjectsToDraw) myObjectsToDraw[i].update();
}

myObjectsToDraw.push ( ... some object ... );
animate();

((如果你有兴趣,这里是我使用的动画循环: http://jsfiddle.net/gamealchemist/KVDsc/
我的基地摆弄了一堆小工具 http://jsfiddle.net/gamealchemist/Vn2Nt/))