重复的倒数计时器在浏览器刷新后仍会持续

时间:2018-07-12 16:01:42

标签: javascript

首先,我对javascript非常陌生。我有一个Shopify商店,并且我打算在每个产品页面上设置一个类似于Amazon的倒数计时器。我知道有很多可以用于Shopify的插件,但是它们都不符合Shopify商店的主题和风格,因此我打算自己做一个。

我想要的是,如果User-1打开我的网站并导航到产品页面,他应该看到一个倒计时到特定时间的计时器,例如12:00:00(hh:mm:ss)。假设用户1看到'Deal ends in 11:20:10'现在,如果用户2同时打开相同的产品页面,那么他也应该看到'Deal ends in 11:20:10'的全部意思是计时器不应该刷新回{ {1}}每次浏览器加载/重新加载页面时,网站上的每个用户都应该在倒数计时器上看到相同的剩余时间。

我从一些研究开始,设法在商店中运行计时器。这不是我想要的,但这是代码:

12:00:00

这是它的样子:

enter image description here

它确实可以工作,但是存在以下问题:

  1. 随浏览器刷新而刷新。
  2. 没有时间。
  3. 当计时器为零时,它不会自动重复。
  4. 每个用户的剩余时间各不相同。

正如我提到的那样,我几乎是JavaScript的入门者。谁能帮助我建立一个克服上述问题的倒计时计时器?

2 个答案:

答案 0 :(得分:1)

我不确定Shopify如何处理插件,但是必须有某种方法可以为它们编辑CSS,这样您就可以使它们与主题样式匹配。

在您提供的JS中,您在此处所做的操作始终会具有该行为,因为它是客户端代码。该脚本将在每次刷新后运行,并将始终将值minutesseconds刷新为关联的初始值15。我相信这可以回答您的第一个问题。

根据第二个问题,您显然没有在该JS脚本中编码hours。因此,hours不应该出现,如果出现的话将是一个谜!

关于第三个问题,在countdown函数中,您只需调用一次onload

根据第一个答案,很自然地,不应在用户之间同步时钟,因为在逻辑上他们会在不同时间刷新页面。

所以我认为最好的选择是使用其中一个插件,然后修改CSS。

答案 1 :(得分:1)

说明

问题1:随着浏览器刷新而刷新。

原因::因为您对秒和分钟进行了硬编码(var seconds = 5var minutes = 1),所以每个访问该页面的用户都将看到计时器从完全相同的值开始递减计数一次又一次地“剩下1分5秒”。

解决方案:与其硬编码倒计时的开始值,不硬编码截止日期。因此,您不必对页面的每个访问者说“从1分5秒开始倒数到0!”,而是说“从现在开始倒数到午夜!”。这样,倒计时将始终在您网站的不同用户之间同步(假设他们的计算机时钟设置正确)。

问题2:没有时间。

原因:您的代码中只有用于跟踪秒和分钟的变量,而没有编写用于跟踪小时的代码。

解决方案:如问题1的解决方案中所建议的:不要跟踪剩余的小时/分钟/秒,而只能跟踪截止日期,然后计算小时/分钟/秒剩余时间取决于当前客户时间。

问题3:当计时器达到零时,它不会自动重复。

原因:代码中嵌套的if(检查seconds == 0m == 0)明确显示了“倒数结束!”文本。倒计时结束后。

解决方案::保留一个条件以检查倒计时何时结束,而不是显示“倒数结束!”,而是将截止日期重置为下一个截止日期。

问题4:对于每个用户,剩余时间各不相同。

原因:请参阅问题1

解决方案:请参阅问题1

示例代码

下面是一段代码,其中集成了上述解决方案:

const span = document.getElementById('countdown')

const deadline = new Date
deadline.setHours(0)
deadline.setMinutes(0)
deadline.setSeconds(0)

function displayRemainingTime() {
  if (deadline < new Date) deadline.setDate(deadline.getDate() + 1)
  const remainingTime = deadline - new Date
  const extract = (maximum, factor) => Math.floor((remainingTime % maximum) / factor)
  const seconds = extract(   60000, 1000   ) 
  const minutes = extract( 3600000, 60000  ) 
  const hours   = extract(86400000, 3600000)
  const string = `${hours} hours ${minutes} minutes ${seconds} seconds remaining`
  span.innerText = `${hours} hours ${minutes} minutes ${seconds} seconds remaining`
}
window.setInterval(displayRemainingTime, 1000)
displayRemainingTime()
<h3>
  <span id="countdown"></span>
</h3>

编辑:确保客户时间正确

如果您不信任客户正确设置时间。您还可以从为您的页面提供服务的服务器发送正确的时间戳。由于我不知道您使用的是哪种服务器,因此无法为您的服务器代码提供示例。但是,基本上,您需要使用在服务器上生成的正确时间戳替换const trustedTimestamp =(即(new Date).getTime()之后的代码(来自以下示例)。有关此时间戳的正确格式,请参考Date.prototype.getTime()

const span = document.getElementById('countdown')
const trustedTimestamp = (new Date).getTime()
let timeDrift = trustedTimestamp - (new Date)
const now = () => new Date(timeDrift + (new Date).getTime())

const deadline = now()
deadline.setHours(0)
deadline.setMinutes(0)
deadline.setSeconds(0)

function displayRemainingTime() {
  if (deadline < now()) deadline.setDate(deadline.getDate() + 1)
  const remainingTime = deadline - now()
  const extract = (maximum, factor) => Math.floor((remainingTime % maximum) / factor)
  const seconds = extract(   60000, 1000   ) 
  const minutes = extract( 3600000, 60000  ) 
  const hours   = extract(86400000, 3600000)
  span.innerText = `${hours} hours ${minutes} minutes ${seconds} seconds remaining`
}
window.setInterval(displayRemainingTime, 1000)
displayRemainingTime()
<h3>
  <span id="countdown"></span>
</h3>

来自Google服务器的时间

为了创建一个有效的示例,我添加了此实验,从Google页面获取正确的时间。不要在您的网站上使用此代码,因为不能保证Google会永远托管该网页。

const span = document.getElementById('countdown')
const trustedTimestamp = (new Date).getTime()
let timeDrift = 0
const now = () => new Date(timeDrift + (new Date).getTime())

const deadline = now()
deadline.setHours(0)
deadline.setMinutes(0)
deadline.setSeconds(0)

window.setInterval(displayRemainingTime, 1000)
window.setInterval(syncClock, 3000)
displayRemainingTime()
syncClock()

function displayRemainingTime() {
  if (deadline < now()) deadline.setDate(deadline.getDate() + 1)
  const remainingTime = deadline - now()
  const extract = (maximum, factor) => Math.floor((remainingTime % maximum) / factor)
  const seconds = extract(   60000, 1000   ) 
  const minutes = extract( 3600000, 60000  ) 
  const hours   = extract(86400000, 3600000)
  span.innerText = `${hours} hours ${minutes} minutes ${seconds} seconds remaining`
}

function syncClock() {
  const xmlhttp = new XMLHttpRequest();
  xmlhttp.open("HEAD", "http://www.googleapis.com",true);
  xmlhttp.onreadystatechange = function() {
    const referenceTime = new Date
    if (xmlhttp.readyState==4) {
      const correctTime = new Date(xmlhttp.getResponseHeader("Date"))
      timeDrift = correctTime - referenceTime
    }
  }
  xmlhttp.send(null);
}
<h3>
  <span id="countdown"></span>
</h3>

相关问题