【问题标题】:Stop and run again timer via pure javascript通过纯javascript停止并再次运行计时器
【发布时间】:2016-02-21 08:04:29
【问题描述】:

我想制作一个简单的倒数计时器,可以通过 + 或 - 设置,也可以通过单击自身来停止和运行。 我的问题是当它停止然后运行时,它显示第一个数字的 NAN。 我想这是因为setTimer 函数,但我不知道如何解决。这是我的代码:

var x = document.getElementsByClassName('session');
var seconds = 60;
var session;
var t;
var on = true;
var minutes = 1;

for (var i = 0; i < x.length; i++) {
  x[i].innerHTML = minutes;
}

function increase() {
  minutes++;
  for (var i = 0; i < x.length; i++) {
    x[i].innerHTML = minutes;
  }
}

function decrease() {
  minutes--;
  for (var i = 0; i < x.length; i++) {
    if (x[i].innerHTML > 0) {
      x[i].innerHTML = minutes;
    }
  }
}

function setSession() {
  session = x[1].innerHTML - 1;
}

function timer() {
  if (seconds > 0) {
    seconds--;
    if (seconds == 0 && session > 0) {
      session--;
      seconds = 60;
    }
  }
  x[1].innerHTML = session + ':' + seconds;
}


function stoptimer() {
  clearInterval(t);
}


function general() {
  if (on) {
    on = false;
    t = setInterval(timer, 100);
  } else {
    on = true;
    stoptimer();
  }
}
<div class='session'></div>
<div id='increase' onclick='decrease()'>-</div>
<div id='increase' onclick='increase()'>+</div>
<div class='session' onclick='setSession();general()'></div>

【问题讨论】:

标签: javascript


【解决方案1】:

您不应该从 html 实体设置会话。基本上,这会产生解析问题,并可能破坏您的代码。此外,每次获得此值时都会减去一个,从而在工作中使用扳手。

我对您的代码进行了一些重新洗牌并添加了一些注释,看看:

var x = document.getElementsByClassName('session');
var seconds = 0;
var session;
var timer; // give this a useful name
var timerRunning = false; // give this a useful name
var minutes = 1;



function updateMinutes(newMinutes){

    if (timerRunning){
        return; // do not allow updating of countdown while count down is running
    }

    if(newMinutes !== undefined){ // allow this function to be called without any parameters
        minutes = newMinutes; 
    }

    if(minutes < 1){
        minutes = 1; //set your minimum allowed value
    }
    if(minutes > 99999){
        minutes = 99999; //could also have some sort of maximum;
    }

    for (var i = 0; i < x.length; i++) {
      x[i].innerHTML = minutes;
    }

    session = minutes; // now this can only be set while timer is not running, so no need to get it from the html
    //also, i would let this start at the exact same value as minutes, and have seconds start at zero
}

updateMinutes(); // call this now to initialise the display

function increase() {
  updateMinutes(minutes + 1);
}

function decrease() {
  updateMinutes(minutes - 1);
}

function timer_tick() {
  if (seconds > 0) {
    seconds--;
    if (seconds == -1 && session > 0) { //because of where you've positioned your logic, this should check for negative one, no zero, otherwise you'll never display a zero seconds value
      session--;
      seconds = 59; //when a timer clocks over it goes to 59
    }
  }
  if (session > 0 || seconds > 0){
      x[1].innerHTML = session + ':' + seconds;
  }
  else{// you need to detect the ending
      x[1].innerHTML = "Finished!!";
  }
}

function timer_stop() {
    clearInterval(timer);
}

function timer_start(){
    timer = setInterval(timer_tick, 1000);
}

function timer_toggle() { //give these timer functions consistent names
  if (!timerRunning) {
    timer_start();
  } else {
    timer_stop();
  }
  timerRunning = !timerRunning; //just flip the boolean
}

【讨论】:

  • 别担心,我实际上并没有运行代码,所以我希望它对你有用!
  • @Armine 请随意选择一个答案。这有助于我们谁给出答案。干杯
【解决方案2】:

你设置

x[1].innerHTML = session + ':' + seconds;

然后尝试将其计算为

session = x[1].innerHTML - 1;

您需要将 session:seconds 放在另一个地方或做

session = parseInt(x[1].innerHTML,10) - 1;

【讨论】:

  • 哦,我明白了。谢谢你的回答。我也试过 session = x[0].innerHTML - 1 ,但在这种情况下,计时器总是从 x[0] 中设置的值开始.
  • mplungjan,我尝试了你的建议(session = parseInt(x[1].innerHTML,10) - 1),它有效,唯一的问题是当计时器停止然后运行时,会话减少 1。
  • 我也试过了,但在这种情况下,示例 2 从 2:59 开始,但应该从 1:59 开始。
  • 由于我不太确定计时器对会话的实际作用,所以我现在要安静了 :)
【解决方案3】:

好的,我会提出另一种方法。使用class 作为您的计时器,如下所示:

function MyTimer(htmlEl) {
  this.sec = 0;
  this.min = 0;
  this.elt = htmlEl;
}

MyTimer.prototype.set = function(m) {
  this.min = m;
  this.display();
  var self = this;
  this._dec = function() {
    self.sec--;
    if (self.sec < 0) {
      if (self.min == 0) {
        self.stop();
      } else {
        self.min -= 1;
        self.sec = 59;
      }
    }
    self.display();
  }
}

MyTimer.prototype.display = function() {
  this.elt.innerHTML = this.min + ":" + this.sec;
}



MyTimer.prototype.toggle = function() {
  if (this.interval) {
    this.stop();
    this.interval = undefined;
  } else this.start();
}

MyTimer.prototype.start = function() {
  this.interval = setInterval(this._dec, 100);
};

MyTimer.prototype.stop = function() {
  clearInterval(this.interval);
};

然后,你可以这样使用它:

window.onload = init;

var minutes, x, timer;

function init() {
  x = document.getElementsByClassName('session');
  timer = new MyTimer(x[1]);
  minutes = 0;
}

function increase() {
  minutes += 1;
  x[0].innerHTML = minutes;
  timer.set(minutes);
}

function decrease() {
  minutes -= 1;
  x[0].innerHTML = minutes;
  timer.set(minutes);
}


function general() {
  timer.toggle();
}

您的 html 中唯一的更改是删除 setSession 调用:

<div id='timer' onclick='general()'></div>

这段代码更清晰。您将逻辑和最小/秒封装在一个可重用的对象中。这是一个有效的小提琴:https://jsfiddle.net/Shitsu/zs7osc59/.

【讨论】:

  • 不客气。如果其中一个答案符合您的需要,请不要忘记通过单击左侧的复选标记将您的问题标记为已解决。您还可以投票多个​​答案。编码愉快!
【解决方案4】:

问题的根源在于代码

    session = x[1].innerHTML - 1;

让我们重新审视保持变量“会话”的目的。我猜是保持最大值的值,分钟的上限,从哪里开始计算,对吧?另一方面,“分钟”变量是保留分钟的临时值。在这里让您感到困惑的是,您使用“分钟”代替了上限(实际上是会话的角色),例如在此代码中

    function increase() {
        minutes++;
        for (var i = 0; i < x.length; i++) {
           x[i].innerHTML = minutes;
        }
    }

看,您正在通过“分钟”的值更新 html,然后您正在通过该邪恶代码将该值读入“会话”:

    session = x[1].innerHTML - 1;

那么,为什么?为什么需要从 html 更新“你的”变量的值?您应该只根据 session var 的值更新 html,反之亦然。让我们继续,让生活更简单…… 让我们将分钟的临时值保留在“分钟”中,让我们也将上限保留在可变会话中,请让我们将其重命名为 maxMinutes。让我们仅在用户单击“+”或“-”时更新“maxMinutes”(从不来自 html)。

<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
</head>
<body>

<script>

var x = document.getElementsByClassName('session');
var maxMinutes = 0;
var minutes = maxMinutes;
var seconds = 0;
var timer;
var on = false;

function increase() {
  if(on) {
    return;
  }
  maxMinutes++;
  minutes = maxMinutes;
  x[0].innerHTML = maxMinutes;
  x[1].innerHTML = minutes;
 }

function decrease() {
  if(on) {
    return;
  }
  if(maxMinutes == 0)
  {
    return;
  }

  maxMinutes--;

  minutes=maxMinutes;

  x[0].innerHTML = maxMinutes;
  x[1].innerHTML = minutes;

}

function periodicRun() {
  if (seconds > 0) {
    seconds--;
  }
  else if(seconds == 0)
  {
   if(minutes > 0) {
      minutes--;
      seconds = 60;
    }
    else
    {
      stopTimer(timer);
      return;
    }
  }
  x[1].innerHTML = minutes + ':' + seconds;
}


function stoptimer() {
  clearInterval(timer);
}


function general() {
  if (on) {
    on = false;
    stoptimer();
  } else {
    on = true;
    timer = setInterval(periodicRun, 500);
  }
}

$(document).ready(function(){
  increase();
});

</script>

<div class='session'></div>
<div id='increase' onclick='decrease()'>-</div>
<div id='increase' onclick='increase()'>+</div>
<div class='session' onclick='general()'></div>

</body>
</html>

注意,maxLimits 被赋值的唯一地方是在 increase() 和 reduction() 中。 “分钟”和 html 依次根据 maxMinutes 进行更新。 祝你好运!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 2023-01-26
    • 2017-09-04
    • 1970-01-01
    • 2017-01-01
    • 1970-01-01
    相关资源
    最近更新 更多