【问题标题】:Progressively draw line animation in canvas在画布中逐步绘制线条动画
【发布时间】:2014-06-29 10:57:43
【问题描述】:

所以我想使用 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,因此不会发生动画。

我不确定如何解决这个问题 - 如何在请求动画帧中传递这些参数?

【问题讨论】:

    标签: javascript jquery html animation canvas


    【解决方案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(),因为当animate() 被定义时,变量centerXcenterY、...和height 都在范围内(即它们当时是已知的)时间,所以你可以简单地在函数内部使用它们)。

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

    【讨论】:

      【解决方案2】:

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

      第二个问题是经典的 javascript 闭包/绑定/范围问题。
      因此,第一个解决方案是切换到更现代的语言,例如 google Dart (:-))。
      例如,其他解决方案是将您的动画函数绑定到其参数。
      在 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/))

      【讨论】:

      • 啊我明白了 - 所以我尝试了这个 - stackoverflow.com/questions/23616171/… 但它不会循环 - 为什么?
      • 你请求一次动画,它不请求任何东西。请删除这个其他问题,它是噪音。希望我的回答可以引导您找到您寻求的解决方案。
      • 所以 requestAnimationFrame 必须使用递归函数?
      • 从技术上讲,这不是递归,但是是的,您必须执行以下操作: function doThing() { callAgainLater(doThing); ...做一些事情...; }
      猜你喜欢
      • 2014-10-18
      • 2013-02-10
      • 2014-07-19
      • 1970-01-01
      • 2013-12-21
      • 1970-01-01
      • 1970-01-01
      • 2020-05-25
      • 1970-01-01
      相关资源
      最近更新 更多