Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/418.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将递归与其他函数连接在一起|画布,JavaScript_Javascript_Animation_Canvas_Recursion - Fatal编程技术网

将递归与其他函数连接在一起|画布,JavaScript

将递归与其他函数连接在一起|画布,JavaScript,javascript,animation,canvas,recursion,Javascript,Animation,Canvas,Recursion,我正在尝试制作一个“成长中的树”的动画。问题是我无法连接下面这两个函数以使其正常工作 到目前为止,我有一个从底部到顶部绘制直线(主干)的函数: 下面是绘制整个树的函数代码: function stick(d) { if (d==0) return; context.beginPath(); context.moveTo(0,70); context.lineTo(0,0); context.lineWidth = 3; con

我正在尝试制作一个“成长中的树”的动画。问题是我无法连接下面这两个函数以使其正常工作

到目前为止,我有一个从底部到顶部绘制直线(主干)的函数:

下面是绘制整个树的函数代码:

function stick(d) {

    if (d==0)
        return;

    context.beginPath();
    context.moveTo(0,70);
    context.lineTo(0,0);
    context.lineWidth = 3;
    context.strokeStyle = 'gray';
    context.stroke();

    if (d==1) {
        context.strokeStyle = 'green';
        context.stroke(); }


    context.save();
    context.scale(0.75,0.75);
    context.translate(-35,-60);
    context.rotate(-30 * Math.PI/180);
    stick(d-1);
    context.restore();


    context.save();
    context.scale(0.75,0.75);
    context.translate(35,-60);
    context.rotate(30 * Math.PI/180);
    stick(d-1);
    context.restore();
}

stick(17);

我尝试了一些选择,但没有一个给出正确的结果,所以我决定寻求一些帮助

动画的问题是你必须分步分割算法

这意味着您必须将递归算法转换为迭代算法

为此,您可以:

  • 粘贴功能拆分为子功能[]:

  • 不要调用函数,而是将调用推送到队列(数组)并循环它:

    function stick(n, i) {
        function main(d, i) {
            // Note the order of pushing is the inverse!
            // You must push first the last function
    
            if(i) queue.push([], post);
            if(d > 0) {
                queue.push([d-1,-1], main);
                queue.push([d-1,1], main);
                queue.push([d], middle);
            }
            if(i) queue.push([i], pre);
        }
    
        queue.push([n, 0], main);
    
        while(queue.length) {
            (queue.pop()).apply(null, queue.pop());
        }
    }
    
  • 完整代码[]:

    现在,将其转换为动画非常简单。只需将while循环替换为以下内容:

    (function step() {
        if (queue.length) {
            (queue.pop()).apply(null, queue.pop());
            setTimeout(step, 100);
        }
    })();
    
    但是,由于只有
    main
    函数会进行视觉变化,因此最好使用[]

    或者,您可能希望在每个步骤中执行更多操作,[]:


    警告:您的小提琴使用
    设置间隔
    ,但从不停止!请确保使用
    clearInterval
    ,或者最好使用带有条件的
    setTimeout
    。非常感谢!!这真的很有帮助。我会处理代码。
    function stick(n, i) {
        var queue = [];
    
        function pre(i) {
            context.save();
            context.scale(0.75,0.75);
            context.translate(i * 35,-60);
            context.rotate(i * 30 * Math.PI/180); 
        }
        function post() {
            context.restore();
        }
        function middle(d) {
            context.beginPath();
            context.moveTo(0,70);
            context.lineTo(0,0);
            context.lineWidth = 3;
            context.strokeStyle = 'gray';
            context.stroke();
    
            if (d==1) {
                context.strokeStyle = 'green';
                context.stroke();
            }
        }
        function main(d, i) {
            if(i) queue.push([], post);
            if(d > 0) {
                queue.push([d-1,-1], main);
                queue.push([d-1,1], main);
                queue.push([d], middle);
            }
            if(i) queue.push([i], pre);
        }
    
        queue.push([n, 0], main);
    
        while(queue.length) {
            (queue.pop()).apply(null, queue.pop());
        }
    }
    
    (function step() {
        if (queue.length) {
            (queue.pop()).apply(null, queue.pop());
            setTimeout(step, 100);
        }
    })();
    
    (function step() {
        if (queue.length) {
            var f = queue.pop(),
                args = queue.pop();
            f.apply(null, args);
            if(f === main) setTimeout(step, 100);
            else step();
        }
    })();
    
    var iter = 1000;
    (function step() {
        var i = iter,
            d = new Date();
        while (queue.length && --i>=0) {
            var f = queue.pop(),
                args = queue.pop();
            f.apply(null, args);
        }
        iter = Math.max(50, iter*60/(new Date()-d)|0);
        if (queue.length) f === main ? setTimeout(step, 100) : step();
    })();