【问题标题】:applying setTimeout to recursive tree in p5.js将 setTimeout 应用于 p5.js 中的递归树
【发布时间】:2020-06-12 13:20:37
【问题描述】:

我正在使用 p5.js 在 html5 convas 中创建生长树。
我想平滑地生成以下树,而不是一次生成。

function setup(){ 
  createCanvas(600,600); 
  noLoop(); 
} 

function draw(){ 
  background(255);    
  strokeWeight(10); 
  translate(width/2,height-20); 
  branch(0); 
} 

function branch(depth){ 
  if (depth < 10) { 
    line(0,0,0,-height/10); // draw a line going up
    { 
      translate(0,-height/10); // move the space upwards
      rotate(random(-0.05,0.05));  // random wiggle

      if (random(1.0) < 0.6){ // branching   
        rotate(0.3); // rotate to the right
        scale(0.8); // scale down
        
        push(); // now save the transform state
        branch(depth + 1); // start a new branch!
        pop(); // go back to saved state
        
        rotate(-0.6); // rotate back to the left 
        
        push(); // save state
        branch(depth + 1);   // start a second new branch 
        pop(); // back to saved state        
     } 
      else { // no branch - continue at the same depth  
        branch(depth);
      } 
    } 
  }
} 


function mouseReleased(){ 
  redraw();  
}
html, body {
  margin: 0;
  padding: 0;
}
<script src="https://cdn.jsdelivr.net/npm/p5@0.10.2/lib/p5.js"></script>
<!DOCTYPE html><html><head>
  </head>
  <body>
    <script src="sketch.js"></script>
  

</body></html>

我正在使用 setTimeout 函数来延迟每个递归分支以使树顺利生长。
但是得到了意想不到的形状

function setup(){ 
  createCanvas(600,600); 
  noLoop(); 
} 

function draw(){ 
  background(255);    
  strokeWeight(10); 
  translate(width/2,height-20); 
  branch(0); 
} 

function branch(depth){ 
setTimeout(function() {
  if (depth < 10) { 
    line(0,0,0,-height/10); // draw a line going up
    { 
      translate(0,-height/10); // move the space upwards
      rotate(random(-0.05,0.05));  // random wiggle

      if (random(1.0) < 0.6){ // branching   
        rotate(0.3); // rotate to the right
        scale(0.8); // scale down
        
        push(); // now save the transform state
        branch(depth + 1); // start a new branch!
        pop(); // go back to saved state
        
        rotate(-0.6); // rotate back to the left 
        
        push(); // save state
        branch(depth + 1);   // start a second new branch 
        pop(); // back to saved state        
     } 
      else { // no branch - continue at the same depth  
        branch(depth);
      } 
    } 
  }
}, 500);
} 


function mouseReleased(){ 
  redraw();  
}
html, body {
  margin: 0;
  padding: 0;
}
<script src="https://cdn.jsdelivr.net/npm/p5@0.10.2/lib/p5.js"></script>
<!DOCTYPE html><html><head>
  </head>
  <body>
    <script src="sketch.js"></script>
  

</body></html>

请提供任何解决方案以使树顺利生长(而不是立即)。

【问题讨论】:

    标签: javascript recursion html5-canvas settimeout p5.js


    【解决方案1】:

    您可以为此使用asyncawait

    1. 定义一个实用函数,返回一个在给定延迟后解决的承诺:

      const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
      
    2. 将您的branch 函数设为async(只需在其前面加上该关键字即可)。

    3. 在您进行的三个递归调用中的每一个之前添加await。例如:

      await branch(depth+1);
      
    4. 添加新行来引入延迟:

      if (depth < 10) {
          await delay(10); // "sleep" for 10 milliseconds.
          // ...
      

    结果:

    function setup(){ 
      createCanvas(600,600); 
      noLoop(); 
    } 
    
    function draw(){ 
      background(255);    
      strokeWeight(10); 
      translate(width/2,height-20); 
      branch(0); 
    } 
    
    const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
    
    async function branch(depth){ 
      if (depth < 10) { 
        await delay(10);
        line(0,0,0,-height/10); // draw a line going up
        { 
          translate(0,-height/10); // move the space upwards
          rotate(random(-0.05,0.05));  // random wiggle
    
          if (random(1.0) < 0.6){ // branching   
            rotate(0.3); // rotate to the right
            scale(0.8); // scale down
            
            push(); // now save the transform state
            await branch(depth + 1); // start a new branch!
            pop(); // go back to saved state
            
            rotate(-0.6); // rotate back to the left 
            
            push(); // save state
            await branch(depth + 1);   // start a second new branch 
            pop(); // back to saved state        
         } 
          else { // no branch - continue at the same depth  
            await branch(depth);
          } 
        } 
      }
    } 
    
    
    function mouseReleased(){ 
      redraw();  
    }
    &lt;script src="https://cdn.jsdelivr.net/npm/p5@0.10.2/lib/p5.js"&gt;&lt;/script&gt;

    请注意,mouseReleased 函数可能会在仍有异步绘图链进行时被调用。这将导致发生意外的混合绘图。

    您可以通过使用警卫暂时“禁用”该功能来避免这种情况,如下所示:

    1. 定义一个全局变量busy = false

    2. 通过将函数draw 更改为:

      在绘图的开始/结束时管理该变量:
      function draw(){ 
        if (busy) return; // guard against concurrent drawing activity
        busy = true; // set guard
        background(255);    
        strokeWeight(10); 
        translate(width/2,height-20); 
        branch(0).then(() => busy = false); // clear guard asynchronously
      } 
      

    function setup(){ 
      createCanvas(600,600); 
      noLoop(); 
    } 
    
    let busy = false;
    function draw(){ 
      if (busy) return; // guard against concurrent drawing activity
      busy = true; // set guard
      background(255);    
      strokeWeight(10); 
      translate(width/2,height-20); 
      branch(0).then(() => busy = false); // clear guard asynchronously
    } 
    
    const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
    
    async function branch(depth){ 
      if (depth < 10) { 
        await delay(10);
        line(0,0,0,-height/10); // draw a line going up
        { 
          translate(0,-height/10); // move the space upwards
          rotate(random(-0.05,0.05));  // random wiggle
    
          if (random(1.0) < 0.6){ // branching   
            rotate(0.3); // rotate to the right
            scale(0.8); // scale down
            
            push(); // now save the transform state
            await branch(depth + 1); // start a new branch!
            pop(); // go back to saved state
            
            rotate(-0.6); // rotate back to the left 
            
            push(); // save state
            await branch(depth + 1);   // start a second new branch 
            pop(); // back to saved state        
         } 
          else { // no branch - continue at the same depth  
            await branch(depth);
          } 
        } 
      }
    } 
    
    
    function mouseReleased(){ 
      redraw();  
    }
    &lt;script src="https://cdn.jsdelivr.net/npm/p5@0.10.2/lib/p5.js"&gt;&lt;/script&gt;

    【讨论】:

    • 感谢@trincot,您解决了造成延迟的主要问题。
    • 还要注意您可能会发现有用信息的附加内容。
    猜你喜欢
    • 1970-01-01
    • 2012-05-26
    • 1970-01-01
    • 2011-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多