Javascript,如何让函数以正确的顺序正确运行

Javascript,如何让函数以正确的顺序正确运行,javascript,function,canvas,setinterval,Javascript,Function,Canvas,Setinterval,今天下午的大部分时间我都在研究/实验这个基本的冥想应用程序,我只是在几个小时自己寻找解决方案后才问这个问题 冥想应用程序应该有3列,分别代表吸气、屏住和呼气,以秒为单位。每次列/时间达到其设置时间时,列暂停,下一列开始增加高度,秒计数器位于其下方。当所有三列完成时,呼吸周期计数器增加1,所有栏重置,过程继续,直到选项卡关闭。当前时间为5吸气:20保持:15呼气 我让所有的杆都均匀地增加,但在改变工作顺序的过程中,杆完全停止了移动。我现在只包括所有的代码,因为我不知道这里什么是重要的。再次感谢你的

今天下午的大部分时间我都在研究/实验这个基本的冥想应用程序,我只是在几个小时自己寻找解决方案后才问这个问题

冥想应用程序应该有3列,分别代表吸气、屏住和呼气,以秒为单位。每次列/时间达到其设置时间时,列暂停,下一列开始增加高度,秒计数器位于其下方。当所有三列完成时,呼吸周期计数器增加1,所有栏重置,过程继续,直到选项卡关闭。当前时间为5吸气:20保持:15呼气

我让所有的杆都均匀地增加,但在改变工作顺序的过程中,杆完全停止了移动。我现在只包括所有的代码,因为我不知道这里什么是重要的。再次感谢你的建议

var canvas=document.getElementById'canvas'; var ctx=canvas.getContext'2d'; //列x1==xPos,x2==width,y1==yPos,y2==height x1a=10,x2a=50,y1a=250,y2a=-10; x1b=50,x2b=50,y1b=250,y2b=-10; x1c=100,x2c=50,y1c=250,y2c=-10; 吸入时间=5; 保持时间=20; 呼气时间=10; 呼吸计数器=0; timerA=1; timerB=1; timerC=1; 函数渲染{ //画背景 ctx.fillStyle=49faff; ctx.fillRect0,0700500; //画A列 ctx.fillStyle=045f84; ctx.fillRectx1a、y1a、x2a、y2a; //绘制B列 ctx.fillStyle=14fe14; ctx.fillRectx1b、y1b、x2b、y2b; //绘制C列 ctx.fillStyle=d600f0; ctx.fillRectx1c、y1c、x2c、y2c; //在A列下写入秒数计数器 ctx.fillStyle=红色; ctx.font=48px衬线; ctx.strokeTexttimerA,10300; //在B列下写入秒数计数器 ctx.fillStyle=红色; ctx.font=48px衬线; ctx.strokeTexttimerB,50,300; //在C列下写入秒计数器 ctx.fillStyle=红色; ctx.font=48px衬线; ctx.strokeTexttimerC,100300; //将呼吸周期计数器写在列上方 ctx.fillStyle=红色; ctx.font=48px衬线; ctx.strokeTextBreath循环:+breathCounter,10100; } //将A列的高度增加1个单位,并将秒计数器增加1个单位 函数渲染{ x1a+=0; x2a+=0; y1a+=0; y2a+=-100; timerA+=1; } //将B列高度增加1个单位,并将秒计数器增加1个单位 函数renderB{ x1b+=0; x2b+=0; y1b+=0; y2b+=-100; timerB+=1; } //将C列高度增加1个单位,并将秒计数器增加1个单位 功能渲染{ x1c+=0; x2c+=0; y1c+=0; y2c+=-100; timerC+=1; } //在每个呼吸周期后重置柱高度&向呼吸周期计数器添加1 函数渲染集{ x1a=10,x2a=50,y1a=250,y2a=-10; x1b=50,x2b=50,y1b=250,y2b=-10; x1c=100,x2c=50,y1c=250,y2c=-10; 呼吸计数器+=1; } 函数更新程序{ 伦德拉; renderB; renderC; //setIntervalrenderA,1000; //setIntervalrenderB,1000; //setIntervalrenderC,1000; } /* 如果timerA>吸入时间{ timerA=1; x1a=10,x2a=50,y1a=250,y2a=-10; x1b=50,x2b=50,y1b=250,y2b=-10; x1c=100,x2c=50,y1c=250,y2c=-10; } 如果timerA>吸入时间&&timerB>保持时间{ timerA=1; x1a=10,x2a=50,y1a=250,y2a=-10; x1b=50,x2b=50,y1b=250,y2b=-10; x1c=100,x2c=50,y1c=250,y2c=-10; } 如果timerA>吸气时间和呼气时间RB>保持时间和呼气时间{ timerA=1; x1a=10,x2a=50,y1a=250,y2a=-10; x1b=50,x2b=50,y1b=250,y2b=-10; x1c=100,x2c=50,y1c=250,y2c=-10; } } 呼吸功能{ //增加barA x1a+=0;x2a+=0;y1a+=0;y2a+=10; //增加timerA timerA+=1; //检查计时器是否>时间 } 功能性屏气{ //增加倒钩x1b+=0;x2b+=0;y1b+=0;y2b+=10; //增加timerB timerB+=1; //检查计时器是否>保持时间 } 呼气功能{ //增加barC x1c+=0;x2c+=0;y1c+=0;y2c+=10; //增加timerC timerC+=1; //检查计时器是否>呼气时间 } */ 提供 伦德拉; // //插入连续增加列高、秒数计数器和呼吸计数器的函数 // 好的,我咬

这是一个呼吸条版本,它使用单个requestAnimationFrame循环而不是多个计时器

关键是计算当前呼吸周期内经过的时间

鉴于:

// milliseconds for each part of the breathing cycle
var maxInhale=5000;
var maxHold=20000;
var maxExhale=15000;
如果经过的时间小于5秒

// where each pct is between 0.00 & 1.00 (==0% to 100%)
pctInhale = elapsed / maxCycleTime
pctHold = 0;
pctExhale = 0;
pctInhale=1;
pctHold=(elapsed-maxInhale)/maxHold;
pctExhale = 0;
如果经过的时间小于5+20 25秒

// where each pct is between 0.00 & 1.00 (==0% to 100%)
pctInhale = elapsed / maxCycleTime
pctHold = 0;
pctExhale = 0;
pctInhale=1;
pctHold=(elapsed-maxInhale)/maxHold;
pctExhale = 0;
如果经过的时间<5+20+15 40秒

pctInhale=1;
pctHold=1;
pctExhale=(elapsed-maxInhale-maxHold)/maxExhale
示例代码和演示:

请在完整屏幕中查看演示 n模式:- var canvas=document.getElementByIdcanvas; var ctx=canvas.getContext2d; var cw=画布宽度; var ch=画布高度; var最大吸入量=5000; var-maxHold=20000; var Max呼气=15000; var maxCycle=最大吸气+最大保持+最大呼气; var cycleStartTime=0; var xa=50; var xb=150; var xc=250; var宽度=75; var maxHeight=300; var maxY=ch-100; ctx.font='36px verdana'; ctx.textAlign='center'; ctx.textbrealine='middle'; 请求动画帧动画; 函数drawpctInhale,pctHold,pctExhale{ ctx.fillStyle=49faff; ctx.fillRect0,0,cw,ch; //画A列 ctx.fillStyle=045f84; ctx.fillRectxa,maxY,宽度,-maxHeight*pctInhale; //绘制B列 ctx.fillStyle=14fe14; ctx.fillRectxb,maxY,width,-maxHeight*pctHold; //绘制C列 ctx.fillStyle=d600f0; ctx.fillRectxc,maxY,width,-maxHeight*pctExhale; ctx.fillStyle='red'; ctx.FillTextParseIntMaxInosis*pctInhale/1000+'s',xa+宽度/2,maxY-48; ctx.filltextpasseintmaxhold*pctHold/1000+'s',xb+宽度/2,maxY-48; ctx.FILLTEXTPARSEINTMAXSEATLE*pctExhale/1000+'s',xc+宽度/2,最大为48; } 函数动画时间{ var经过=时间周期开始时间; //循环结束?重新开始。 If>maxCycle{ cycleStartTime=时间; 经过=0; } //根据经过的时间计算每个条形的百分比 var pctInhale=0; var-pctHold=0; var pctExhale=0;
ifeloped我尽量坚持使用您现有的代码,并添加了我需要添加的内容。在代码的底部,我添加了以下内容:

var whichCounter = 'A';

function newUpdate() {
  //console.log('newUpdate, A=' + timerA + ', B=' + timerB + ', C=' + timerC);

  render();
  switch (whichCounter) {
    case 'A':
      if (timerA < inhaleTime) {
        renderA();
      } else {
        timerB = 1;
        whichCounter = 'B';
      }
      break;
    case 'B':
      if (timerB < holdTime) {
        renderB();
      } else {
        timerC = 1;
        whichCounter = 'C';
      }
      break;
    case 'C':
      if (timerC < exhaleTime) {
        renderC();
      } else {
        whichCounter = 'Q';
      }
      break;
    case 'Q':
      timerA = 1;
      timerB = 1;
      timerC = 1;
      renderReset();
      whichCounter = 'A';
      render();
      break;
  }
}
setInterval(newUpdate, 1000);

您可以在中看到它的作用。

我看到代码时的第一个想法是,您需要重构所有这些变量:使用对象数组,特别是一个包含三个元素的数组,每个元素都是一个保存列状态的对象。这将整理代码,并使函数更容易为任何列设置动画当前的一个。nnnnnnnnnn,非常感谢,我将研究该缓存Staheli,我尽可能做到最小、完整和可验证,同时仍然尽可能保持我要做的事情的清晰性。所有这些评论都是添加的,一些代码的重新安排/删除完全是为了在这里发布。你需要定期调用updateRender。将此添加到该函数的末尾requestAnimationFrameupdateRender RAF在每个帧的末尾,这将定期再次调用更新。下一次RAF将使用时间调用该函数,因此添加updateRenderframeTime您现在的时间为1/1000秒。如果您希望在20秒内发生某些事情其次,为该时间设置一个变量nextEvent=frameTime+20*1000,然后设置ifframeTime>nextEvent{调用所需内容并设置RAF解释的下一个任务,阅读w3c,这以一种令人耳目一新的简单简洁的方式解释了这个概念。这太棒了。我在对象重构方面取得了进展,但我只想添加一个呼吸周期计数器,每35秒增加1,直到我弄清楚到底是什么继续这段代码。非常感谢你,我真的很惊讶我在这么短的时间内得到了这么多好的回复。向所有人竖起大拇指,希望我很快就能熟练地回答问题并获得一些分数,这样大拇指就会显示出来。大家继续努力吧。