倒数计时器'延迟'标签何时无效?

时间:2016-10-01 14:48:25

标签: javascript css animation countdown tweenmax

尝试构建一个非常简单的Javascript倒计时。但是,每当选项卡处于非活动状态时,倒计时开始滞后并保持不正确的计数。

请参阅此处的jsfiddle,例如:https://jsfiddle.net/gbx4ftcn/

function initTimer(t) {

  var self = this,
    timerEl = document.querySelector('.timer'),
    minutesGroupEl = timerEl.querySelector('.minutes-group'),
    secondsGroupEl = timerEl.querySelector('.seconds-group'),

    minutesGroup = {
      firstNum: minutesGroupEl.querySelector('.first'),
      secondNum: minutesGroupEl.querySelector('.second')
    },

    secondsGroup = {
      firstNum: secondsGroupEl.querySelector('.first'),
      secondNum: secondsGroupEl.querySelector('.second')
    };

  var time = {
    min: t.split(':')[0],
    sec: t.split(':')[1]
  };

  var timeNumbers;

  function updateTimer() {

    var timestr;
    var date = new Date();

    date.setHours(0);
    date.setMinutes(time.min);
    date.setSeconds(time.sec);

    var newDate = new Date(date.valueOf() - 1000);
    var temp = newDate.toTimeString().split(" ");
    var tempsplit = temp[0].split(':');

    time.min = tempsplit[1];
    time.sec = tempsplit[2];

    timestr = time.min + time.sec;
    timeNumbers = timestr.split('');
    updateTimerDisplay(timeNumbers);

    if (timestr === '0000')
      countdownFinished();

    if (timestr != '0000')
      setTimeout(updateTimer, 1000);

  }

  function animateNum(group, arrayValue) {

    TweenMax.killTweensOf(group.querySelector('.number-grp-wrp'));
    TweenMax.to(group.querySelector('.number-grp-wrp'), 1, {
      y: -group.querySelector('.num-' + arrayValue).offsetTop
    });

  }

  setTimeout(updateTimer, 1000);

}

我不确定问题是动画还是JS代码本身。

为了澄清:我希望倒计时在标签处于非活动状态时继续,或者“赶上自己”#39;当标签重新进入焦点时。

我知道setTimeoutsetInterval会导致非活动标签出现问题,但我并不完全确定如何解决这个问题。

任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:2)

为此,您可以使用HTML5 Visibility API检测浏览器选项卡是否处于活动状态。并使用事件处理程序的常规绑定来实现浏览器窗口的焦点和模糊。

基本上,当您模糊选项卡时,.时间轴,然后pause(),当您给选项卡重新聚焦时。这个实例的例子:

<强> http://codepen.io/jonathan/pen/sxgJl

play()

HTML5可见性文档:

https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API

关于GreenSock论坛主题:

http://forums.greensock.com/topic/9059-cross-browser-to-detect-tab-or-window-is-active-so-animations-stay-in-sync-using-html5-visibility-api/

同样在GSAP中,setTimeout()的等价物是// Set the name of the hidden property and the change event for visibility var hidden, visibilityChange; if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support hidden = "hidden"; visibilityChange = "visibilitychange"; } else if (typeof document.mozHidden !== "undefined") { hidden = "mozHidden"; visibilityChange = "mozvisibilitychange"; } else if (typeof document.msHidden !== "undefined") { hidden = "msHidden"; visibilityChange = "msvisibilitychange"; } else if (typeof document.webkitHidden !== "undefined") { hidden = "webkitHidden"; visibilityChange = "webkitvisibilitychange"; } // If the page is hidden, pause the video; // if the page is shown, play the video function handleVisibilityChange() { if (document[hidden]) { tl.pause(); } else { tl.play(); } } // Warn if the browser doesn't support addEventListener or the Page Visibility API if (typeof document.addEventListener === "undefined" || typeof document[hidden] === "undefined") { // do nothing or throw error via alert() alert("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API."); } else { // Handle page visibility change // Pause timeline tl.pause(); }

  

提供一种在一定时间(或帧)后调用函数的简单方法。您也可以选择将任意数量的参数传递给函数。

GSAP delayedCall():http://greensock.com/docs/#/HTML5/GSAP/TweenMax/delayedCall/

delayedCall()

我希望这有帮助!

答案 1 :(得分:1)

毕竟,我不得不提一下,那些倒计时动画真是出类拔萃,优雅亲爱的先生!干得好......

现在回答: 正如许多文章中所提到的,以下是其中之一:

  

setInterval(func,delay)不保证给定的延迟   处决。有些情况下实际延迟大于或小于   给出。事实上,它并不能保证任何延迟。

来源:http://javascript.info/tutorial/settimeout-setinterval
和..

  

大多数浏览器通过降低优先级来应用性能改进   非活动选项卡上的几个任务,甚至是页面的某些部分   这不在屏幕上。有时这些改进会影响到   也执行Javascript间隔。

来源:How can I make setInterval also work when a tab is inactive in Chrome?

正如您所看到的,他们提到setInterval并不保证执行之间的延迟,即使选项卡处于活动状态,也只是假设setTimeout(你曾经使用过的一个也是一样的,因为它们相对而言是相同的&#34;

那么这个问题的解决方案是什么?
好吧,你实际可以做的是检查事件之间实际经过了多少次,类似这样Codepen

编辑:正如您所要求的,这里有一个fiddle您的倒计时修复,我对小提琴所做的更改//commented,所以它有望让你更容易理解。现在,当您将倒计时与其他计时器(例如您的手机的计时器)配对时,即使选项卡处于非活动状态或帧速率减慢,您也应该得到相同的结果。

如果您对我的回答很满意,请考虑将其标记为&#34;答案&#34;或至少投票;)

答案 2 :(得分:0)

当用户离开选项卡然后返回时,确保计时器保持正确的最简单方法是使用会话存储 - 存储原始开始时间:

在第一次加载时 - 获取本地当前日期时间并存储到会话存储中(注意,它只接受一个字符串 - 因此您必须对该值进行字符串化,然后在检索时再将其解析出来。)

当选项卡失去焦点时,设置开始时间仍将作为startTime存储在ss中。当选项卡重新获得焦点时 - 有一个获取新当前日期时间的函数,从会话存储中获取存储的日期时间并计算差异。然后计时器可以更新到新的缩短时间。

例如,如果页面加载时间为上午10:00 - 将startTime设置为ss。然后用户在网站上花费1分钟并离开现场5分钟。返回时 - 上述过程将确定当前时间是10:06并确定它比起始时间晚6分钟,因此可以更新定时器。

这样就不需要间隔和定时器等。如果需要,可以将特异性降低到ms。而且 - 我也喜欢你的小提琴。