【问题标题】:setInterval() to add class then remove class for same amount of timesetInterval() 添加类然后删除类相同的时间
【发布时间】:2018-02-21 06:23:50
【问题描述】:

我正在尝试制作一个简单的“西蒙游戏”。我目前被困在尝试向 div 添加一个“on”类一秒钟,然后在相同的时间内删除该类。

所以我有四个 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 函数,虽然它有效,但我想知道是否有更好的方法。如果你看我在我的模型对象中使用一个计数变量来跟踪迭代。

到目前为止,这是我完整的 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();
});

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

【问题讨论】:

    标签: javascript jquery recursion settimeout intervals


    【解决方案1】:

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

    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);
    .myClass {
      background-color:yellow;
    }
    <div class="post-text">A</div>
    <div class="post-text">B</div>
    <div class="post-text">C</div>
    <div class="post-text">D</div>

    【讨论】:

      【解决方案2】:

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

      下面的示例并不是真正基于您的代码,只是为了说明这个想法。它从按下按钮数组开始(在代码的按钮处)。这些被传递给getSequence。这将返回一个命令数组,在这种情况下只是要打开的按钮的颜色,因此序列可以是 red,red,red,red,'','','','' 让红灯亮起来4个“间隔”,然后将其关闭4个“间隔”。通过这种方式,您可以创建复杂的序列,并且通过细微的调整,您甚至可以同时点亮多个按钮。

      示例中的时间间隔设置为 1/10 秒。每种颜色播放 10 步(= 1 秒),每个暂停播放 5 步(= 0.5 秒)。在控制台中,您会看到要播放的按钮/颜色的基本数组,然后是播放的更复杂的序列。

      // 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);
      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;
      }
      <div id="red" class="button"></div>
      <div id="green" class="button"></div>
      <div id="yellow" class="button"></div>
      <div id="blue" class="button"></div>

      【讨论】:

        【解决方案3】:

        TLDR ;)

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

        如果/当您希望停止闪烁时,只需使用 clearTimeout()clearInterval()

        这是一个例子:

        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);
        #test {
          width:100px;
          height:100px;
          background-color:blue;  /* <-- blue will be the default color */
        }
        
        #test.lightUp {
          background-color:yellow;
        }
        <div id="test"></div>
        <button>Stop Blinking</button>

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-12-14
          • 2020-06-15
          • 1970-01-01
          • 1970-01-01
          • 2022-01-20
          • 2016-09-10
          • 2012-09-24
          • 2015-07-21
          相关资源
          最近更新 更多