SetInterval()函数无法正确更新页面元素

时间:2019-03-22 21:24:37

标签: javascript html

我正在尝试实现一个计时器,用户可以在其中选择小时数和分钟数,然后当用户按下按钮时就可以实时倒数。我正在使用setInterval()函数来计算剩余时间并更新页面。 SetInterval()每秒应运行一次,但是计时器值仅更新一次(按下按钮时)。

这很奇怪,因为我已经测试了其他功能,这些功能可以在相同范围内写入页面的相同区域,并且这些功能会重复更新(例如不断获取当前日期并输出它;我可以看到秒和分钟)列打勾)。这使我相信问题出在代码退出countDown()函数时如何查看小时/分钟/秒变量,但我似乎无法找出任何原因。

这是我的代码。作为参考,我只是尝试在单个HTMl文件中执行此操作,而无需网络连接。

HTML:

<body>
    <!--section for controlling & displaying round timer-->
    <div name="timeLeft" id="D3">
        Round Timer<br>
        Hours:
        <select name="hours" id="S1">
            <option value="0">0</option>
            <option value="1">1</option>
            <option value="2">2</option>
        </select>
        Minutes:
        <select name="minutes" id="S2">
            <option value="0">0</option>
            <option value="5">5</option>
            <option value="10">10</option>
            <option value="15">15</option>
            <option value="20">20</option>
            <option value="25">25</option>
            <option value="30">30</option>
            <option value="35">35</option>
            <option value="40">40</option>
            <option value="45">45</option>
            <option value="50">50</option>
            <option value="55">55</option>
        </select>
        <br>
        <input type="button" name="countDownStart" id="B2" onclick="countDown()" value="Start Countdown">
        <br>
        Your round will end in <span name="timerDisplay" id="span1">00:00:00</span>
    </div>
</body>

Javascript:

<script type="application/javascript">
        var timerInterval = null;
        var hours;
        var minutes;
        var seconds;
    function countDown() {

        timerInterval = setInterval(function() {
            //get user's inputs for hours and minutes
            hours = parseInt(document.getElementById("S1").value);
            minutes = parseInt(document.getElementById("S2").value);
            seconds = 0; //the user cannot select the # of seconds
            //get current date
            var currentDate = new Date();
            //get the countDownDate, which is the current date plus the user's values
            var countDownDate = new Date();
            countDownDate.setHours(currentDate.getHours() + hours);
            countDownDate.setMinutes(currentDate.getMinutes() + minutes);
            //find the difference between the two dates in hours, minutes, seconds
            var dateDifference = new Date();
            dateDifference = countDownDate - currentDate;
            //convert the values in dateDifference to milliseconds
                //math.floor() here returns the largest integer less than or equal to the appropriate
                //measurement of time, in milliseconds
            hours = Math.floor((dateDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
            minutes = Math.floor((dateDifference % (1000 * 60 * 60)) / (1000 * 60));
            seconds = Math.floor((dateDifference % (1000 * 60)) / 1000);

            //update the countdown timer with these new values every 1000 milliseconds
            document.getElementById("span1").innerHTML = hours + ":" + minutes + ":" + seconds;
        }, 1000);
</script>

2 个答案:

答案 0 :(得分:0)

您的间隔运行良好,但是问题在于一次性初始化代码与更新代码结合在一起了。您需要在setInterval回调的每个刻度上重置计时器,并且计时器始终显示为过期。一种解决方法是将一次性初始化代码与重复更新代码分开,从而为代码提供固定的将来使用时间。

我还建议以是否已存在间隔为条件来启动计时器,否则,如果用户按[Start Countdown]按钮,则会创建一系列间隔并同时运行。

我将变量移出了全局范围,但您可能还考虑使用闭包来维护区间状态,事件侦听器,并提供比"S1""S2",{ {1}}等。

"B2"
var timerInterval = null;

function countDown() {
  if (!timerInterval) {
    var hours = parseInt(document.getElementById("S1").value);
    var minutes = parseInt(document.getElementById("S2").value);
    var countDownDate = new Date();
    countDownDate.setHours(countDownDate.getHours() + hours);
    countDownDate.setMinutes(countDownDate.getMinutes() + minutes);
      
    timerInterval = setInterval(function () {
      var dateDifference = countDownDate - new Date();
      var hours = Math.floor((dateDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
      var minutes = Math.floor((dateDifference % (1000 * 60 * 60)) / (1000 * 60));
      var seconds = Math.floor((dateDifference % (1000 * 60)) / 1000);
      document.getElementById("span1").innerHTML = `${hours}:${minutes}:${seconds}`;
    }, 1000);  
  }
}

答案 1 :(得分:0)

这是一个简单的修复程序。我认为您不需要所有日期逻辑。其他所有内容都可以保持不变。这将基于总时间中的秒存储当前时间。每个循环将其推断为一个小时/分钟/秒,然后增加自您开始以来经过的秒数。这将大大简化该过程,并且可能更具可读性。试试看:

    var startedTimeStamp;
    var timerInterval = null;
    var secondsAccrued = 0;
    var initialTimer = 0;
    function countDown() {

        //Let's set this once and be done with it. It is the total number of seconds that the user has selected for their count down.
        initialTimer = (parseInt(document.getElementById("S1").value) * 3600) + (parseInt(document.getElementById("S2").value) * 60);
        startedTimeStamp = new Date();

    timerInterval = setInterval(function() {

        //How many seconds are left in the countdown?
        secondsAccrued = (new Date() - startedTimeStamp) / 1000;
        var currentTime = initialTimer - secondsAccrued;

        //How many hours/minutes/seconds? Convert these to seconds, and make sure to subtract the hours from the total, and then minutes from the total, before determining the seconds the user should see.
        var hours = Math.floor(currentTime / 3600);
        var minutes = Math.floor((currentTime - (hours * 3600)) / 60);
        var seconds = Math.round(Math.abs(currentTime - (currentTime - (hours * 3600)) - (currentTime -(minutes * 60))));
        document.getElementById("span1").innerHTML = hours + ":" + minutes + ":" + seconds;

    }, 1000);

}

编辑:已编辑,可以再次使用DateTimes来确保每个注释的准确性。经过测试并可以正常工作。