setInterval()添加类,然后删除类相同的时间

时间:2017-09-12 17:26:50

标签: javascript jquery recursion settimeout intervals

我正在尝试制作一个简单的西蒙游戏'。我目前无法尝试添加课程' on'到一个div一秒钟,然后删除该类相同的时间。

所以我有四个div,我根据一系列数字打开和关闭,例如[0, 1, 2, 3]。这会使div[0]闪烁一秒钟然后关闭一秒钟然后移至div[1],开启和关闭等等。

这是我的功能

/**
 * sequence => array [0, 1, 2, 3]
 * speed    => int 1000 (one second)
 */
playSequence: function(sequence, speed){
    var self = this;

    // removes class 'on'
    view.turnOffPads();
    setTimeout(function(){
        // adds the 'on' class to a specific div
        view.lightUpPad(model.startupSequence[model.count]);
    }, speed / 2);

    setTimeout(function(){
        model.count++; // keeps track of the iterations
        if (model.count < sequence.length) { // if we are still iterating
            self.playSequence(sequence, speed); // light up the next div
        } else {
            model.count = 0; // set back to zero
        }
    }, speed);
},

这个问题是我正在使用两个setTimeout函数,虽然它有效,但我想知道是否有更好的方法。如果你看我在模型对象中使用count变量来跟踪迭代。

到目前为止,这是我的完整javascript应用程序......

$(function(){

    var model = {
        on: false,
        strictMode: false,
        startupSequence: [0, 1, 2, 3, 3, 3, 2, 1, 0, 3, 2, 1, 0, 2, 1, 3],
        score: 0,
        sequence: [],
        count: 0,
    }

    var controller = {
        init: function(){
            view.cacheDOM();
            view.bindEvents();
        },
        getSequence: function(){
            // get a random number from one to 4
            var random = Math.floor(Math.random() * 4);
            // push it to the sequence array
            model.sequence.push(random);
            console.log(model.sequence);
            // play it
            this.playSequence(model.sequence);
        },

        /**
         * sequence => array [0, 1, 2, 3]
         * speed    => int 1000 (one second)
         */
        playSequence: function(sequence, speed){
            console.log(sequence.length);
            var self = this;

            view.turnOffPads();
            setTimeout(function(){
                view.lightUpPad(model.startupSequence[model.count]);
            }, speed / 2);

            setTimeout(function(){
                model.count++;
                if (model.count < sequence.length) {
                    self.playSequence(sequence, speed);
                } else {
                    model.count = 0;
                }
            }, speed);
            // view.turnOffPads();
        },
    }

    var view = {
        cacheDOM: function(){
            this.$round  = $('#round');
            this.$start  = $('#start');
            this.$strict = $('#strict');
            this.$pad    = $('.pad');

            this.$padArray = document.getElementsByClassName('pad');
        },
        bindEvents: function(){
            this.$start .change(this.start.bind(this));
            this.$strict.change(this.setStrictMode.bind(this));
        },
        start: function(){
            // turn on pads
            if (model.on) {
                this.$pad.removeClass('on');
                this.$round.text('--');
                model.on = false;
                // reset everything
            } else {
                this.$round.text(model.score);
                model.on = true;
                controller.playSequence(model.startupSequence, 100)
                // controller.getSequence();
            }
        },
        lightUpPad: function(i){
            $(this.$padArray[i]).addClass('on');
        },
        turnOffPads: function(){
            this.$pad.removeClass('on');
        },
        setStrictMode: function(){
            if (model.strictMode) {
                model.strictMode = false;
            } else {
                model.strictMode = true;
            }
        }
    }

    controller.init();
});

是否有更简洁的方法来添加类,然后删除一个类?

3 个答案:

答案 0 :(得分:1)

TLDR;)

您需要做的就是使用setInterval()setTimeout()并在回调函数中使用 element.classList.toggle() 来添加或删除元素中的类。

如果您希望停止闪烁,请使用clearTimeout()clearInterval()

以下是一个例子:

&#13;
&#13;
var d = document.getElementById("test");
var b = document.querySelector("button");

b.addEventListener("click", function(){
  // Cancel the timer
  clearTimeout(timer);
});

// Assign the timer's ID to a variable so that
// you can stop it later
var timer = setInterval(function(){
  // Toggle the use of the lightUp class
  test.classList.toggle("lightUp");
},1000);
&#13;
#test {
  width:100px;
  height:100px;
  background-color:blue;  /* <-- blue will be the default color */
}

#test.lightUp {
  background-color:yellow;
}
&#13;
<div id="test"></div>
<button>Stop Blinking</button>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

我认为您可以将按钮列表转换为一系列命令。然后,您可以使用单个setInterval来播放命令,直到命令用完为止。 setInterval可以使用1秒间隔,如果您想要打开和关闭同样长,但您也可以将其设置为更快一点,以便轻松地允许不同的持续时间。

以下示例并非基于您的代码,只是为了说明这个想法。它按下一组按钮开始(在代码的按钮处)。这些传递给getSequence。这将返回一组命令,在这种情况下只是要打开的按钮的颜色,因此序列可以是红色,红色,红色,红色,&#39;&#39;&#39;&#39;&#39;&#39 ;,&#39;&#39;&#39;&#39;为4&#39;间隔点亮红灯,然后关闭4&#39;间隔&#39;。通过这种方式,您可以创建复杂的序列,只需稍作调整,您甚至可以同时点亮多个按钮。

示例中的间隔设置为1/10秒。每种颜色播放10个步骤(= 1秒),每个暂停播放5个步骤(= .5秒)。在控制台中,您可以看到要播放的按钮/颜色的基础数组,然后是更精细的序列。

&#13;
&#13;
// The play function plays a sequence of commands
function play(sequence) {
  var index = 0;
  var lastid = '';
  var timer = setInterval(function(){
    // End the timer when at the end of the array 
    if (++index >= sequence.length) {
      clearInterval(timer);
      return;
    }
    var newid = sequence[index];
     
    if (lastid != newid) {
      // Something has changed. Check and act.
  
      if (lastid != '') {
      // The last id was set, so lets switch that off first.
        document.getElementById(lastid).classList.remove('on');
        console.log('--- ' + lastid + ' off');
      }
      
      if (newid != '') {
        // New id is set, switch it on
        document.getElementById(newid).classList.add('on');
        console.log('+++ ' + newid + ' on');
      }
      lastid = newid;
    }
  }, 100);
}

// generateSequence takes a list of buttons and converts them to a 
// sequence of color/off commands.
function generateSequence(buttons) {
  var result = [];
  for (var b = 0; b < buttons.length; b++) {
    // 'On' for 10 counts
    for (var i = 0; i < 10; i++) {
      result.push(buttons[b]);
    }
    if (b+1 < buttons.length) {
      // 'Off' for 5 counts
      for (var i = 0; i < 5; i++) {
        result.push('');
      }
    }
  }
  // One 'off' at the end
  result.push('');
  
  return result;
}

var buttons = ['red', 'green', 'red', 'yellow', 'yellow', 'blue'];
console.log(buttons);
var sequence = generateSequence(buttons);
console.log(sequence);
play(sequence);
&#13;
div.button {
  width: 100px;
  height: 100px;
  opacity: .5;
  display: inline-block;
}
div.button.on {
  opacity: 1;
}
#red {
  background-color: red;
}
#green {
  background-color: green;
}
#yellow {
  background-color: yellow;
}
#blue {
  background-color: blue;
}
&#13;
<div id="red" class="button"></div>
<div id="green" class="button"></div>
<div id="yellow" class="button"></div>
<div id="blue" class="button"></div>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

使用setInterval而不是setTimeout我创建了四个divison并使每个分区闪烁1秒。

&#13;
&#13;
var i = 0,
    j = 4;

function blink(i) {
  new Promise(function(resolve, reject) {
  x = setTimeout(function() {
    document.querySelectorAll(".post-text")[i].classList.add("myClass");
    resolve("added");
  }, 1000)
  }).then(function(a) {
  new Promise(function(res, rej) {
    setTimeout(function() {
      clearInterval(x);
      document.querySelectorAll(".post-text")[i].classList.remove("myClass");
      res("deleted");
    }, 1000)
  }).then(function(a) {
    i++;
    if (i < j) {
      blink(i);
    } else {
      i = 0;
      blink(i);
    }
  });

  });
}
blink(i);
&#13;
.myClass {
  background-color:yellow;
}
&#13;
<div class="post-text">A</div>
<div class="post-text">B</div>
<div class="post-text">C</div>
<div class="post-text">D</div>
&#13;
&#13;
&#13;