Javascript,如何让函数正常运行&按正确的顺序

时间:2016-04-17 04:21:16

标签: javascript function canvas setinterval

我今天下午的大部分时间都在研究/试验这个基本的冥想应用程序,并且只是在我自己找到解决方案后数小时才提出这个问题。

冥想应用程序应该有3列代表吸气,保持和呼气,以秒为单位。每次列/时间达到它设置的时间,该列暂停,下一列开始增加高度并且秒计数器低于它。当所有三列都达到完成时,呼吸循环计数器增加1,所有条都重置,并且过程继续,直到标签关闭。 (当前时间为5(吸气):20(保持):15(呼气)。

我让所有的酒吧均匀增加,但是在按顺序改变工作的过程中,酒吧完全停止了。我现在只包括我现有的所有代码,因为我不知道这里有什么重要的。再次感谢任何想法。

<!DOCTYPE html>
    <html>
    <head>
    <meta charset=utf-8 />
    <Title>Meditation App</title>
    </head>
    <body>
        <canvas id="canvas" width="500" height="500">
    </canvas>

    <script>
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');


     // Columns 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; 

     inhaleTime = 5;
     holdTime = 20;
     exhaleTime = 10;

     breathCounter = 0;

     timerA = 1;
     timerB = 1;
     timerC = 1;


    function render(){


        //Draw background      
        ctx.fillStyle = "#49faff";
        ctx.fillRect(0, 0, 700, 500);     


       //Draw column A
        ctx.fillStyle = "#045f84";
        ctx.fillRect(x1a, y1a, x2a, y2a);


        //Draw column B
        ctx.fillStyle = "#14fe14";
        ctx.fillRect(x1b, y1b, x2b, y2b);

       //Draw column C
        ctx.fillStyle = "#d600f0";
        ctx.fillRect(x1c, y1c, x2c, y2c);


        //Write seconds counter under column A
        ctx.fillStyle = "red"; 
        ctx.font = "48px serif";
        ctx.strokeText(timerA, 10, 300);


       //Write seconds counter under column B
        ctx.fillStyle = "red"; 
        ctx.font = "48px serif";
        ctx.strokeText(timerB, 50, 300);


        //Write seconds counter under column C
        ctx.fillStyle = "red"; 
        ctx.font = "48px serif";
        ctx.strokeText(timerC, 100, 300);


        //Write breath cycles counter above columns 
        ctx.fillStyle = "red"; 
        ctx.font = "48px serif";
        ctx.strokeText(("Breath Cycles: " + breathCounter), 10, 100);


    }


    // Increase column A height by 1 unit & increase seconds counter by 1
    function renderA(){
                    x1a += 0;
                    x2a += 0;
                    y1a += 0;
                    y2a += -100; 

                    timerA += 1;
    }

    // Increase column B height by 1 unit & increase seconds counter by 1
    function renderB(){

                    x1b += 0;
                    x2b += 0;
                    y1b += 0;
                    y2b += -100;

                    timerB += 1;
    }


    // Increase column C height by 1 unit & increase seconds counter by 1
    function renderC(){
                    x1c += 0;
                    x2c += 0;
                    y1c += 0;
                    y2c += -100;

                    timerC += 1;

    }


    //Reset column heights after each breath cycle & add 1 to Breath Cycles counter
    function renderReset(){       
                    x1a = 10, x2a = 50, y1a = 250, y2a = -10; 
                    x1b = 50, x2b = 50, y1b = 250, y2b = -10; 
                    x1c = 100, x2c = 50, y1c = 250, y2c = -10; 

                    breathCounter += 1;

    }




    function updateRender(){

            renderA();
            renderB();
            renderC();



          //  setInterval(renderA, 1000);
            // setInterval(renderB, 1000);
           //  setInterval(renderC, 1000);

    }


    /*
        if (timerA > inhaleTime){
            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; 
        }   


         if (timerA > inhaleTime && timerB > holdTime){
            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; 
        }


         if (timerA > inhaleTime && timerB > holdTime && timerC > exhaleTime){


            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; 
        }          

    }

    function inhaleBreath(){
        //increase barA                         x1a += 0; x2a += 0; y1a += 0; y2a += -10; 

        //increase timerA                        timerA += 1;
        //check if timer > inhaleTime


    }


    function holdBreath(){
        //increase barB                        x1b += 0; x2b += 0; y1b += 0; y2b += -10; 
        //increase timerB                      timerB += 1;
        //check if timer > holdTime
    }


    function exhaleBreath(){
        //increase barC                        x1c += 0; x2c += 0; y1c += 0; y2c += -10; 
        //increase timerC                      timerC += 1;
        //check if timer > exhaleTime
    }

    */


    render();
    renderA();
    //
    //Insert functions to continually increment column heights, seconds counter, and breath counter 
    //
    </script>

2 个答案:

答案 0 :(得分:0)

好的,我会咬人......

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

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

假设:

// milliseconds for each part of the breathing cycle
var maxInhale=5000;
var maxHold=20000;
var maxExhale=15000;
  • 如果经过的时间是&lt; 5秒,

    // where each pct is between 0.00 & 1.00 (==0% to 100%)
    pctInhale = elapsed / maxCycleTime
    pctHold = 0;
    pctExhale = 0;
    
  • 如果经过的时间是&lt; (5 + 20)25秒,

    pctInhale=1;
    pctHold=(elapsed-maxInhale)/maxHold;
    pctExhale = 0;
    
  • 如果经过的时间是&lt; (5 + 20 + 15)40秒,

    pctInhale=1;
    pctHold=1;
    pctExhale=(elapsed-maxInhale-maxHold)/maxExhale
    

示例代码和演示:

请以全屏模式查看演示: - )

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var maxInhale=5000;
var maxHold=20000;
var maxExhale=15000;
var maxCycle=maxInhale+maxHold+maxExhale;
var cycleStartTime=0;
var xa=50;
var xb=150;
var xc=250;
var width=75;
var maxHeight=300;
var maxY=ch-100;

ctx.font='36px verdana';
ctx.textAlign='center';
ctx.textBaseline='middle';

requestAnimationFrame(animate);

function draw(pctInhale,pctHold,pctExhale){
    ctx.fillStyle = "#49faff";
    ctx.fillRect(0,0,cw,ch);     
    //Draw column A
    ctx.fillStyle = "#045f84";
    ctx.fillRect(xa,maxY,width,-maxHeight*pctInhale);
    //Draw column B
    ctx.fillStyle = "#14fe14";
    ctx.fillRect(xb,maxY,width,-maxHeight*pctHold);
    //Draw column C
    ctx.fillStyle = "#d600f0";
    ctx.fillRect(xc,maxY,width,-maxHeight*pctExhale);

    ctx.fillStyle='red';
    ctx.fillText(parseInt(maxInhale*pctInhale/1000)+'s',xa+width/2,maxY-48);
    ctx.fillText(parseInt(maxHold*pctHold/1000)+'s',xb+width/2,maxY-48);
    ctx.fillText(parseInt(maxExhale*pctExhale/1000)+'s',xc+width/2,maxY-48);
}

function animate(time){
    var elapsed=time-cycleStartTime;
    // cycle done? start over.
    if(elapsed>maxCycle){
        cycleStartTime=time;
        elapsed=0;
    }
    // calc each bars percentage based on elapsed time
    var pctInhale=0;
    var pctHold=0;
    var pctExhale=0;    
    if(elapsed<maxInhale){
        pctInhale=elapsed/maxInhale;
    }else if(elapsed<maxInhale+maxHold){
        pctInhale=1;
        pctHold=(elapsed-maxInhale)/maxHold;
    }else if(elapsed<maxInhale+maxHold+maxExhale){
        pctInhale=1;
        pctHold=1;
        pctExhale=(elapsed-maxInhale-maxHold)/maxExhale
    }
    // draw the bars
    draw(pctInhale,pctHold,pctExhale);
    // request another animation loop
    requestAnimationFrame(animate);
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=700 height=500></canvas>

答案 1 :(得分:0)

我尽可能地坚持使用现有代码并添加了我需要添加的内容。在代码的底部,我添加了以下内容:

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);

您可以在this jfiddle中看到它。