【问题标题】:Specify the right time to call a function inside a setInterval指定在 setInterval 内调用函数的正确时间
【发布时间】:2020-07-31 22:35:34
【问题描述】:

我正在尝试编写一个从红色、绿色和蓝色切换的循环,但是当它达到一种颜色的 255 时,它会变成黑色。

我被函数 change() 卡住了,如何指定函数调用内部函数(turnRed、turnGreen、turnBlue)的确切时间?

var r = 0;
var g = 0;
var b = 0;
var dir = true;

function turnRed(){
  if (dir == true){
    r < 256 ? r++ : 0;
    if (r == 255){
      dir = false;
    }else{
      turnBlack;
    }
  }
}

function turnGreen(){
  if (dir == true){
    g < 256 ? g++ : 0;
    if (g == 255){
      dir = false;
    }else{
      turnBlack;
    }
  }
}

function turnBlue(){
  if (dir == true){
    b < 256 ? b++ : 0;
    if (b == 255){
      dir = false;
    } else{
      turnBlack;
    }
  }
}

function turnBlack(){
  b > 0 ? b-- : 0;
  if (b == 0){
    dir = true;
  }

  g > 0 ? g-- : 0;
    if (g == 0){
      dir = true;
    }

  r > 0 ? r-- : 0;
    if (r == 0){
      dir = true;
   }
}

function change() {
    color = 'rgb('+r+', '+g+', '+b+')';
    document.body.style.backgroundColor = color;
    
    setTimeout(turnRed, 1000);
    clearInterval();
    //then
    setTimeout(turnGreen, 1000);
    clearInterval();
    //then
    setTimeout(turnBlue, 1000);
    clearInterval();
}

setInterval(change, 10);
clearInterval();

我的逻辑:如果我将 setTimeout(function, time) 放入 setInterval,它将调用该函数一次,并且 setInterval 将在循环中运行更改颜色,但在我的情况下,该函数只运行一次并停止。

【问题讨论】:

    标签: javascript animation frontend


    【解决方案1】:

    这就是我的做法,而不是尝试在主循环中设置时间间隔。

    intervalstimeouts 很好,但是为了平滑过渡,最好使用requestAnimationFrame。此外,我设置代码的方式只是一个简单的cycle 函数,您只需使用 steps 数组随时间迭代颜色模式。

    另一个注意事项一定要查看template literals,它们对document.body.style.backgroundColor = `rgb(${red},${green},${blue})`;这样的事情很方便

    function cycle(val, target, step = 1) {
      if (val !== target) {
        return val += step;
      }
    
      return val;
    }
    
    const steps = [
      {r: 255, g: 0, b: 0},
      { r: 0, g: 0, b: 255},
      { r: 0 ,g: 255, b: 0},
      { r: 0, g: 0, b: 0 }
    ]
    
    let curStep = 0;
    let red = 0;
    let green = 0;
    let blue = 0;
    
    function colorize() {
      requestAnimationFrame(colorize);
      const step = steps[curStep];
      const {r, g, b} = step;
    
      if (red === r && g === green && b === blue) {
        curStep++;
        if (curStep >= steps.length) {
          curStep = 0;
        }
      } else {
        red = cycle(red, r, r < red ? -1 : 1);
        green = cycle(green, g, g < green ? -1 : 1);
        blue = cycle(blue, b, b < blue ? -1 : 1);
      }
      
      document.body.style.backgroundColor = `rgb(${red},${green},${blue})`;
    }
    
    colorize();

    如果您想实际为每个颜色周期计时,您可以在下一个示例中的主循环之外以这种方式进行。

    所有这一切都是在每次调用 setTimeout 时增加当前活动步骤,在本例中为 1、5 和 8 秒。

    注意它不会在最后一步之后继续,因为在这个例子中每个都被安排了。主要方法保持不变,让带有requestAnimationFrame 的函数实际处理更新。

    function cycle(val, target, step = 1) {
      if (val !== target) {
        return val += step;
      }
    
      return val;
    }
    
    const steps = [
      { r: 0, g: 0, b: 0 },
        {r: 255, g: 0, b: 0},
      { r: 0, g: 0, b: 255},
      { r: 0 ,g: 255, b: 0},
    ]
    
    let curStep = 0;
    let red = 0;
    let green = 0;
    let blue = 0;
    
    function colorize() {
      requestAnimationFrame(colorize);
      const step = steps[curStep];
      const {r, g, b} = step;
    
      red = cycle(red, r, r < red ? -1 : 1);
      green = cycle(green, g, g < green ? -1 : 1);
      blue = cycle(blue, b, b < blue ? -1 : 1);
     
      document.body.style.backgroundColor = `rgb(${red},${green},${blue})`;
    }
    
    
    function nextStep() {
      curStep++;
      if (curStep >= steps.length) {
         curStep = 0;
      }
    }
    
    setTimeout(() => {nextStep()}, 1000);
    setTimeout(() => {nextStep()}, 5000);
    setTimeout(() => {nextStep()}, 8000);
    
    colorize();

    【讨论】:

      【解决方案2】:

      这是一个工作示例。您的代码中有一些错误。在turnBlack 之后,您没有() 来实际调用该函数。我删除了g &gt; 0 ? g-- : 0;,因为您在需要时改变方向,然后就没有关系了。我也不确定更改内部是否需要 setTimeouts。这只会将所有事情的发生延迟 1 秒。

      var r = 0;
      var g = 0;
      var b = 0;
      var dir = true;
      
      function turnRed(){
        if (dir == true) {
          if (r < 256) { 
            r++;
          } else {
            dir = false;
          }
        } else {
          turnBlack();
        }
      }
      
      
      
      function turnGreen(){
        if (dir == true) {
          if (g < 256) { 
            g++;
          } else {
            dir = false;
          }
        } else {
          turnBlack();
        }
      }
      
      
      function turnBlue(){
        if (dir == true) {
          if (b < 256) { 
            b++;
          } else {
            dir = false;
          }
        } else {
          turnBlack();
        }
      }
      
      
      function turnBlack(){
        if (b == 0){
          dir = true;
        } else {
          b--
        }
      
          if (g == 0){
            dir = true;
          } else {
            g--
          }
      
      
          if (r == 0){
            dir = true;
         } else {
          r--
        }
      
      }
      
      function change() {
          color = 'rgb('+r+', '+g+', '+b+')';
          document.body.style.backgroundColor = color;
          
          setTimeout(turnRed, 1000);
          clearInterval();
          setTimeout(turnBlue, 1000);
          clearInterval();
          setTimeout(turnGreen, 1000);
          clearInterval();
      
      }
      
      setInterval(change, 10);
      clearInterval();

      除非你传递一个间隔,否则清除间隔不会做任何事情。但这会阻止你想要的。例如:

      var myVar = setInterval(myTimer, 1000);
      clearInterval(myVar)
      

      我认为这会很好。

      var r = 0;
      var g = 0;
      var b = 0;
      var dir = true;
      
      function turnRed(){
        if (dir == true) {
          if (r < 256) { 
            r++;
          } else {
            dir = false;
          }
        } else {
          turnBlack();
        }
      }
      
      
      
      function turnGreen(){
        if (dir == true) {
          if (g < 256) { 
            g++;
          } else {
            dir = false;
          }
        } else {
          turnBlack();
        }
      }
      
      
      function turnBlue(){
        if (dir == true) {
          if (b < 256) { 
            b++;
          } else {
            dir = false;
          }
        } else {
          turnBlack();
        }
      }
      
      
      function turnBlack(){
        if (b == 0){
          dir = true;
        } else {
          b--
        }
      
          if (g == 0){
            dir = true;
          } else {
            g--
          }
      
      
          if (r == 0){
            dir = true;
         } else {
          r--
        }
      
      }
      
      function change() {
          color = 'rgb('+r+', '+g+', '+b+')';
          document.body.style.backgroundColor = color;
          
          turnRed();
          turnBlue();
          turnGreen();
      
      }
      
      setInterval(change, 10);

      这会单独更改颜色。先红->黑->绿->黑->蓝->黑

      var r = 0;
      var g = 0;
      var b = 0;
      var dir = 'red';
      var nextColor = 'green'
      
      function turnRed(){
        if (dir == 'red') {
          if (r < 256) { 
            r++;
          } else {
            dir = 'black';
            nextColor = 'green'
          }
        }
      }
      
      
      
      function turnGreen(){
        if (dir == 'green') {
          if (g < 256) { 
            g++;
          } else {
            dir = 'black';
            nextColor = 'blue'
          }
        }
      }
      
      
      function turnBlue(){
        if (dir == 'blue') {
          if (b < 256) { 
            b++;
          } else {
            dir = 'black';
            nextColor='red';
          }
        }
      }
      
      
      function turnBlack(){
        if (dir !== 'black') return;
      
        if (b > 0) b--;
        if (r > 0) r--;
        if (g > 0) g--;
      
        if (b <= 0 && r <= 0 && g <= 0) {
          dir = nextColor;
        }
      }
      
      function change() {
          color = 'rgb('+r+', '+g+', '+b+')';
          document.body.style.backgroundColor = color;
          
          turnRed();
          turnBlue();
          turnGreen();
          turnBlack()
      }
      
      setInterval(change, 10);

      最后这会变成红色,然后随着蓝色的增加而减少红色,并继续对所有颜色进行此操作。

      var r = 0;
      var g = 0;
      var b = 0;
      var dir = 'red';
      var nextColor = 'green'
      
      function turnRed(){
        if (dir == 'red') {
          if (r < 256) { 
            r++;
          } else {
            dir = 'green'
          }
        }
      }
      
      
      
      function turnGreen(){
        if (dir == 'green') {
          if (g < 256) { 
            g++;
          } else {
            dir = 'blue'
          }
        }
      }
      
      
      function turnBlue(){
        if (dir == 'blue') {
          if (b < 256) { 
            b++;
          } else {
            dir = 'red';
          }
        }
      }
      
      
      function turnBlack(){
        if (b > 0 && dir !== 'blue') b--;
        if (r > 0 && dir !== 'red') r--;
        if (g > 0 && dir !== 'green') g--;
      }
      
      function change() {
          color = 'rgb('+r+', '+g+', '+b+')';
          document.body.style.backgroundColor = color;
          
          turnRed();
          turnBlue();
          turnGreen();
          turnBlack();
      }
      
      setInterval(change, 10);

      【讨论】:

      • 那你想要什么?它们从黑色变为白色,然后又变回黑色。或者你想让它变成红色 -> 黑色 -> 绿色 -> 黑色 -> 蓝色 -> 黑色?
      • 这是第 3 个演示 - 按照上面的顺序进行。啊,我以为那是 OP,它是另一个回答者。第四种颜色会在增加另一种颜色时减少一种颜色。
      • 谢谢 Diesel,第三个正是我想要的! ;)
      • 完美。还添加了第 4 个颜色,它不会完全变黑 - 增加一种颜色,同时减少另一种颜色。很高兴它有帮助!
      猜你喜欢
      • 1970-01-01
      • 2017-12-27
      • 2018-10-21
      • 1970-01-01
      • 2015-05-26
      • 2019-02-25
      • 1970-01-01
      • 1970-01-01
      • 2021-12-25
      相关资源
      最近更新 更多