繁体   English   中英

JavaScript - 存储页面重新加载的倒计时截止时间

[英]JavaScript - store a countdown time deadline for page reload

所以在这里我创建了一个 10 分钟的倒数计时器,以在按下“开始”按钮时启动。 我想存储这个倒计时,这样当用户离开页面并回到它时,倒计时仍然会进行。 请注意,我不希望倒计时停止,然后在页面重新加载时从停止的地方继续,我希望它继续到指定的截止日期。 有什么建议?

<html>
<head>

</head>
<body>



    <a id="sendButton" class="button" onclick=" startClock();">START</a>

        <div id="sectionClock">

        <div id="clockdiv">
            <div>
                <span class="hours"></span>
                <div class="smalltext">Hours</div>
            </div>
            <div>
                <span class="minutes"></span>
                <div class="smalltext">Minutes</div>
            </div>
            <div>
                <span class="seconds"></span>
                <div class="smalltext">Seconds</div>
            </div>
        </div>
    </div>

    <script>
function getTimeRemaining(endtime) {
    var t = Date.parse(endtime) - Date.parse(new Date());
    var seconds = Math.floor((t / 1000) % 60);
    var minutes = Math.floor((t / 1000 / 60) % 60);
    var hours = Math.floor((t / (1000 * 60 * 60)) % 24);
    return {
        'total': t,
        'hours': hours,
        'minutes': minutes,
        'seconds': seconds
    };
}
var flag = 0;

function startClock() {


    /************ INITIALIZE CLOCK ************/
    function initializeClock(id, endtime) {

        // If countdown time is 0 then operate
        if(flag==0)
        {
            var clock = document.getElementById(id);
            var hoursSpan = clock.querySelector('.hours');
            var minutesSpan = clock.querySelector('.minutes');
            var secondsSpan = clock.querySelector('.seconds');

        flag=1; 
        }


        function updateClock() {
            var t = getTimeRemaining(endtime);


            hoursSpan.innerHTML = ('0' + t.hours).slice(-2);
            minutesSpan.innerHTML = ('0' + t.minutes).slice(-2);
            secondsSpan.innerHTML = ('0' + t.seconds).slice(-2);

            if (t.total <= 0) {
                clearInterval(timeinterval);
                flag=0;
            }
        }

        updateClock();
        var timeinterval = setInterval(updateClock, 1000);
    }

    var timeInMinutes = 10;
    var currentTime = Date.parse(new Date());
    var deadline = new Date(currentTime + timeInMinutes*60*1000);
    initializeClock('clockdiv', deadline);

    document.cookie = deadline

    var cookie = document.cookie;

    console.log(cookie);

}

function sendTrack(){
    (function() {

        var trackUrl = document.getElementById("url");    

    }());
}

    </script>

</body>
</html>

在按钮上单击 - 设置您正在执行的时间,然后将其存储到 localStorage 中。 这将存储倒计时的开始时间。

var designatedStart_time = //time that the button was clicked;
localStorage.setItem('startTime',designatedStart_time);

然后添加一个函数,在页面加载(或文档就绪)时确定当前时间。 这可以与存储的开始时间进行比较,然后可以计算差异并将其从倒数计时器中删除。 然后倒计时可以在新的时间开始。 请注意,存储的值将是一个字符串,因此您需要对其进行解析以获取数字形式的时间。

$(document).ready(function(){
var startTime = localStorage.getItem('designatedStart_time');
var currentTime = //mechanism to get current time;
var remainingTime = startTime - currentTime;
//reset coundown to remainingTime
})

例如,如果您将 10 分钟设置为 10:00,并且您在页面上停留 1 分钟,然后离开页面,两分钟后返回,则新的倒计时时间将从 7:00 开始。

这样您就不必存储用户在页面上的时间长度或他们离开的时间——它只是当前时间减去指定的开始时间。

这是一把小提琴

关键是将初始挂钟时间仅存储在“开始时间”变量中,而不是预先计算“截止日期”时间,然后将其存储在会话存储中,以防您离开或重新加载页面:

var timeStamp = Date.now(), // Set timeStamp to current wall clock time in ms
    timeDelta;

    // if startTime not set, put current timeStamp in session storage
    // and set startTime to timeStamp
    startTime = startTime || getSetStartTime(timeStamp);

然后,每当您更新显示的时间(并检查计时器是否已完成倒计时),通过从开始时间减去当前挂钟时间来制作时间增量(自存储的开始时间以来经过的时间):

timeDelta = timeStamp - startTime;

然后,如果 delta 大于最大倒计时时间,则只显示剩余时间为零,否则,将倒计时时间显示为总倒计时时间 - 时间增量:

if (timeDelta > timerMaxMS) {
  // ... stuff
  timeElem.value = msToTimeStr(0); // display zero time left
  // ... stuff
  return; // return, ending calling of countdown routine
}
timeElem.value = msToTimeStr(timerMaxMS - timeDelta); // Display time left
requestID = window.requestAnimationFrame(updateTime); // call countdown routine via rAF at next repaint cycle

如果自上次调用更新例程以来的时间出现暂停,则无所谓,因为每次调用时您都在抓取挂钟时间,并根据挂钟时间正确计算每次的时间增量,即使自调用更新逻辑以来已经过去了几分钟。

就我而言,我使用window.requestAnimationFrame()而不是 setInterval()。 虽然它提供了一个时间戳参数,但它不是挂钟时间,而是自导航开始以来的时间,因此时间将在重新加载时重置。 rAF 在浏览器的自然绘制周期上更新,因此是定期更新动态更改 UI 元素的首选方法。

在 getSetStartTime() 中,我首先尝试从会话存储中获取开始时间。 如果存在,我将其转换为整数并返回。 如果没有,则假定我没有运行计时器或显示计时器已完成,因此我使用 timeStamp 参数将其设置在会话存储中(将其转换为字符串后),然后返回时间戳:

function getSetStartTime(timeStamp) {
  var startTimeStr = sessionStorage.getItem('startTime');

  if (!startTimeStr) {
    sessionStorage.setItem('startTime', String(timeStamp));
    return timeStamp;
  }
  return parseInt(startTimeStr, 10);
}

还有一个 clearStartTime() 将 startTime 变量设置为 null 并从 sessionStorage 中删除“startTime”键/值对。

如果包含开始时间键/值对,则逻辑使用会话存储在页面重新加载或导航离开和返回时重新启动倒数计时器。 如果计时器处于停止状态,并且应该显示零和绿色背景等,此逻辑仍将在第一次(也是唯一一次)运行 updateTime() 时反映这一点:

if (sessionStorage.getItem('startTime')) {
  startTime = null;
  labelElem.innerText = RUNNING_TEXT;
  requestID = window.requestAnimationFrame(updateTime);
}

JavaScript:

(function() {
  'use strict';

  var FINISHED_COLOR = '#0f0',
    DEFAULT_COLOR = '#fff',
    RUNNING_TEXT = 'Countdown Time Left:',
    STOPPED_TEXT = 'Countdown Finished!',
    MS_PER_SEC = 1000,
    MS_PER_MIN = MS_PER_SEC * 60,
    timerMaxMS = 2 * MS_PER_MIN,
    startTime,
    requestID = null;

  function getSetStartTime(timeStamp) {
    var startTimeStr = sessionStorage.getItem('startTime');

    if (!startTimeStr) {
      sessionStorage.setItem('startTime', String(timeStamp));
      return timeStamp;
    }
    return parseInt(startTimeStr, 10);
  }

  function clearStartTime() {
    startTime = null;
    sessionStorage.removeItem('startTime');
  }

  function pad(num, digits) {
    return String((num / Math.pow(10, digits)).toFixed(digits)).slice(-digits);
  }

  function msToTimeStr(timeInMS) {
    var secs = Math.floor(timeInMS / MS_PER_SEC) % 60,
      mins = Math.floor(timeInMS / MS_PER_MIN) % 60;

    return pad(mins, 2) + ':' + pad(secs, 2) + '.' + pad(timeInMS % 1000, 3);
  }

  window.addEventListener('load', function() {
    var startElem = document.getElementById('start'),
      clearElem = document.getElementById('clear'),
      timeElem = document.getElementById('time'),
      labelElem = document.getElementById('label'),
      idleText = labelElem.innerText;

    function updateTime() {
      var timeStamp = Date.now(),
        timeDelta;

      startTime = startTime || getSetStartTime(timeStamp);
      timeDelta = timeStamp - startTime;

      if (timeDelta > timerMaxMS) {
        labelElem.innerText = STOPPED_TEXT;
        timeElem.value = msToTimeStr(0);
        timeElem.style.background = FINISHED_COLOR;
        // clearStartTime();
        if (requestID) {
          window.cancelAnimationFrame(requestID);
          requestID = null;
        }
        return;
      }
      timeElem.value = msToTimeStr(timerMaxMS - timeDelta);
      requestID = window.requestAnimationFrame(updateTime);
    }

    clearElem.addEventListener('click', function(event) {
      event.preventDefault();
      if (requestID) {
          window.cancelAnimationFrame(requestID);
          requestID = null;
        }
        labelElem.innerText = idleText;
        timeElem.value = '';
        timeElem.style.background = DEFAULT_COLOR;
                clearStartTime();
        return false;
    });

    startElem.addEventListener('click', function(event) {
      event.preventDefault();
      clearStartTime();
      labelElem.innerText = RUNNING_TEXT;
      timeElem.style.background = DEFAULT_COLOR;
      requestID = window.requestAnimationFrame(updateTime);
      return false;
    }, false);

    if (sessionStorage.getItem('startTime')) {
      startTime = null;
      labelElem.innerText = RUNNING_TEXT;
      requestID = window.requestAnimationFrame(updateTime);
    }
  }, false)
}());

HTML:

<form>
  <fieldset>
    <legend>Timer</legend>
    <p>
      <button id="start">Start Timer</button>
      <button id="clear">Clear Timer</button>
    </p>
    <p>
      <label for="time" id='label'>Timer Not Running</label>
      <input type="text" name="time" id="time" readonly="true" />
    </p>
  </fieldset>
</form>

CSS:

label {
  padding-right: 10px;
  text-align: right;
  display: inline-block;
  width: 150px;
}

input {
  width: 75px;
  height: 20px;
  text-align: right;
  padding-right: 5px;
  font-family: "Courier New";
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM