团购类网站倒计时的js实现

这篇文章发布于 2010年07月27日,星期二,17:21,归类于 JS实例。 阅读 248534 次, 今日 2 次 55 条评论

 

一、如火如荼的团购网站

根据易观国际提供的统计数据,截至2010年6月,中国市场团购网站数量已经突破400家。国内团购潮从今年2月份开始出现,在4~6月出现高峰,尤其是今年5月,一些大的网站如爱帮网、开心网都加入到团购中来,F团、团宝、酷团、515团购、1288团购、拉手、24券、满座、窝窝、满堂网、糯米网、第一团购等也纷纷上线。预计年底,我国团购类网站的数量将达到1000多家,甚至有业内人士称“一天之内会有三到五家新的团购网站诞生”。俗称“千团大战”。

据说王兴的美团网上线4个月就盈亏平衡了,还有,貌似企鹅、点评也来插足了。

不过这类团购网站是死是活、孰好孰坏不管我鸟事,我所关心的是一些让我感兴趣的前端内容,比如说,这类团购网站的倒计时。
美团网倒计时 张鑫旭-鑫空间-鑫生活企鹅团倒计时张鑫旭-鑫空间-鑫生活点评团倒计时 张鑫旭-鑫空间-鑫生活

虽然有的横着睡觉,有的竖着休息,本质上都是一样的,一样的阿拉伯数字,一样的一秒一变化。本文内容就是展示如何在前端使用js实现倒计时的UI效果。

二、demo与效果展示

为节约时间,我就直接套用了企鹅团的界面作为demo的背景。因为是倒计时,所以需要一个固定的时间,为了n年后,某位仁兄打开demo页面依然在倒计时,所以我把倒计时时间设成了2050年7月30日中午12点整,还有40年才到,因为年代较长,所以有必要显示剩余年份与月份。所以,最后demo页面的效果如下图所示:
demo页面关键部位截图 张鑫旭-鑫空间-鑫生活

您可以狠狠地点击这里:团购倒计时demo

三、使用

倒计时其实就是Date类的一些计算与处理,主要是些繁琐的工作。为了省掉他人的功夫以及方便后来的使用,我已经将倒计时主要处理方法封装起来了。方法名为:fnTimeCountDown(参数1, 参数2)

具体使用如下,首先,调用倒计时js脚本,您可以在页面的任何位置嵌入这段脚本:

<script type="text/javascript" src="https://www.zhangxinxu.com/study/js/timeCountDown.js"></script>

然后,调用方法fnTimeCountDown(参数1, 参数2)即可,于是就可以实现倒计时效果了,很简单吧。

下面是重点了,就是关于这里的参数。参数1指的是截止的时间。我个人建议使用UTC()方法创建Date对象传递给Date构造函数。例如,Date.UTC(2030, 6, 27, 16, 34),表示的就是2030年7月27日161时34分0秒(月份需要加1),然后将这个参数替换“参数1”就可以了。具体来说就是:

var d = Date.UTC(2030, 6, 27, 16, 34);
fnTimeCountDown(d, 参数2)

关于参数2,有点小复杂。参数2是个对象,同时也是个对象集,是显示秒、分、时数值标签的DOM对象集合,里面的对象名是固定的,不可自己定义,否则没有效果的。考虑到扩展性,对象名从秒一直到年,具体如下:

{
     sec: 显示秒数值的标签对象,
     mini: 显示分钟数值的标签对象,
     hour: 显示小时数值的标签对象,
     day: 显示天数数值的标签对象,
     month: 显示月份数值的标签对象,
     year: 显示年数数值的标签对象
}

以上所有的参数都是可选的,如果哪个参数没有,则不显示时间变化,如果参数对应的DOM对象不存在,自然也没有数值变化的。如果是上面部分展示的团购倒计时的话,只要下面三个子对象就足够了:

{
     sec: 显示秒数值的标签对象,
     mini: 显示分钟数值的标签对象,
     hour: 显示小时数值的标签对象
}

举个例子吧,有三个标签,分别用来显示剩余的小时数,分钟数以及秒数的,其id分别是hour,mini,sec,如下所示:

<span id="hour"></span>时 <span id="mini"></span>分 <span id="sec"></span>秒

则第二个参数应该这么写:

var obj = {
     sec: document.getElementById("sec"),
     mini: document.getElementById("mini"),
     hour: document.getElementById("hour")
}

所以两个参数合起来就是:

var d = Date.UTC(2030, 6, 27, 16, 34);
var obj = {
     sec: document.getElementById("sec"),
     mini: document.getElementById("mini"),
     hour: document.getElementById("hour")
}
fnTimeCountDown(d, obj);

这段实例代码所产生的效果如下所示:
000

如果现在还没有到2030年,则您应该可以看到上面秒前面的数值在不停的倒计时。

需要注意的是,参数2的对象集不支持jQuery对象,只能是DOM对象,如果您需要支持jQuery对象,需要修改原js方法中的innerHTML为jQuery的html()或是text()方法。

最后,提供下js脚本的下载,您可以狠狠地点击这里:timeCountDown.js(1.75K, 右键 – [目标|链接]另存为)

四、简短的结语

此脚本只是个人简单测试了下,且js功力尚浅,难免还存有bug或是不准确之处。如果您发现了,欢迎指正,不甚感谢。也欢迎各种形式的讨论与交流。

(本篇完)

分享到:


发表评论(目前55 条评论)

  1. WEB大白说道:

    还有33年08月26天19小时22分08秒

  2. 天涯浅唱说道:

    if(o.sec){
    o.sec.innerHTML = f.dv().sec;
    }
    if(o.mini){
    o.mini.innerHTML = f.dv().mini;
    }
    if(o.hour){
    o.hour.innerHTML = f.dv().hour;
    }
    if(o.day){
    o.day.innerHTML = f.dv().day;
    }
    if(o.month){
    o.month.innerHTML = f.dv().month;
    }
    if(o.year){
    o.year.innerHTML = f.dv().year;
    }

    这段这样写是不是更好些?
    for (var i in o) {
    o[i].innerHTML = f.dv()[i];
    }

  3. lagolas说道:

    大神,等你老了走不动了,打开页面一看,倒计时还继续呢~~~

  4. oldlei说道:

    感谢!!!

  5. fingerpasser说道:

    取整用parseInt好点,时间这些不存在上舍下舍

  6. small说道:

    好厉害。

  7. stephen说道:

    如果页面有多个 地方需要显示倒计时,怎么做使用?

  8. 慕唯说道:

    改了本地时钟,倒计时就变了。

  9. 帮帮客说道:

    jQ 插件就好了 厉害!

  10. gayayang说道:

    你好,张大哥,能把http://www.zhangxinxu.com/wordpress/?p=987完整的代码奉献下吗?我是PHP的不怎么懂js。谢谢

  11. jie说道:

    不显示月跟年 天数不正确
    比如我是到2013年 天数还只是几天

  12. 微笑小婷说道:

    张哥,您这个貌似通用性不强啊,月份按30天算,那2月份呢?1,3,5,7,8,10,12份呢?貌似就不准确了哦~

  13. 近墨者说道:

    发现站长是个很有才的人,这段时间我得下定决心认真学学JQ了

  14. 其实这样麻烦的要死,像下面这样写,简单明了。说道:

    下面的代码拷回去,放到网页上去,马上可以用。IE,火狐等主流浏览器都兼容。

    function _fresh() {
    var endtime = new Date(“2011/11/3,17:00:00”);
    var nowtime = new Date();
    var leftsecond = parseInt((endtime.getTime() – nowtime.getTime()) / 1000);
    __d = parseInt(leftsecond / 3600 / 24);
    __h = parseInt((leftsecond / 3600) % 24);
    __m = parseInt((leftsecond / 60) % 60);
    __s = parseInt(leftsecond % 60);
    document.getElementById(“times”).innerHTML = “” + __d + “天 ” + “” + __h + “” + “小时 ” + “” + __m + “” + “分 ” + “” + __s + “” + “秒”;
    if (leftsecond <= 0) {
    document.getElementById("times").innerHTML = "抢购已结束";
    clearInterval(sh);
    }
    }
    _fresh()
    var sh;
    sh = setInterval(_fresh, 1000);

  15. 西施说道:

    为什么我运行代码的时候,没有时间啊?只有时 分 秒?

  16. cykjydxs说道:

    如何把剩余的年和月变成天呢!!!急救啊

  17. edayshop说道:

    还有一个问题,就是说 隐藏的时间为什么就不显示了

    比如说我隐藏了“月” 那样子在“日”上应该加上才对呀 ,要不然 这个时间 显示很有局限的

  18. edayshop说道:

    很不错,我找了一下午没有找到合作的 相对来说 张哥这个是很不错的, 能实现 一页多次调用

  19. linzhuzhang说道:

    如果客户在本地电脑调整了一下时间,那就出现问题了,明明团购时间已经过了,但是还是可以团购!

  20. 阿亮说道:

    我明白了,原来是没有显示月那个字段

  21. dleung说道:

    很好,很给力

  22. 吉光片羽说道:

    呃,我实在是纳闷了,今天是2011年7月25日,DEMO上的到期时间是2050年7月30日,而倒计时显示的是39年00月29天……25日跟30日隔了29天?我不解了……

  23. flysky1001说道:

    大哥我也做到个倒计时功能,发现个问题,(IE下)页面打开后右击鼠标的菜单,菜单弹出来后,时间就停止了,给JS加的断点也没有进, 是不是ie右击出来的菜单阻塞了JS?不晓得要怎么处理了

  24. yqy3483说道:

    我想做个团购一个页面多个团购,并且多个倒计时进行。可我循环出来的是第一个倒计时正常,而后面的却没啥反映了,我知道这是变量问题.应该怎么做呀。QQ:44404234,请回复,我用的是ASPX

  25. 小点儿说道:

    你好,我是一个地地道道的菜鸟,我非常喜欢你的这个倒计时作品,我想问一下,怎么在html写代码实现?能不能给一个全的?有点急···谢谢你·
    不好意思,这么麻烦你···

  26. 如家说道:

    多谢。找了很久了。很详细!

  27. Edisontsai说道:

    这个只读本地时间的是不可信的,要读服务器的时间才是最佳的做法,假如用户更改一下本地的日期,这个倒计时就没有意义了。

  28. 左右之旅说道:

    大哥 脚本下载了 不知道怎么用啊

  29. 张涛说道:

    好东西,我用了 不错。。可以做个扩展功能,例如 倒计时数字利用调用样式背景的方法 就可以换成各种 艺术字了。。不过思路就要变一下

  30. 安检门说道:

    这个确实是很实用,但是要有点功底才行啊~~~

  31. LQ说道:

    我想问下future.getTimezoneOffset() * 60,这段怎么理解呢。两者的时间毫秒差为什么要加上这段,能否解答下。谢谢。。

    • sp42说道:

      同问+1

    • 叶落萧萧说道:

      //程序并非直接使用new Date()取的客户端操作系统的时间,而是服务器的时间(Linux事先与某一台时间服务器校对过时间–为北京时间)。而产生问题的根源在于,服务器将它当前时间转成毫秒数后传递给客户端,客户端显示的时候没有进行时差修正。使用getTimezoneOffset()可解决这个问题,因为它返回的是格林威治时间与本地时间之间的时差,而使用new Date()得到的结果,还是相对于本地时间的显示,所以想真正实现客户端与服务器端显示的时间一致,需要做如下调整:先使用timezoneOffset()【此方法返回的是分钟】方法获取差值,这个就得到的是格林威治时间,而北京时间相对于它是需要再加上8小时的,也就是 8 * 60 = 480分钟。这样修正后,再调用格式化方法来显示时间就正常了。

      • calmcarry说道:

        date.getTime方法返回的是本地时间,getTimezoneOffset() * 60是为了修正不同地区的时间差,这也是楼主建议参数1使用UTC的原因,不知道我理解的对吗(不过getTimezoneOffset()返回的是与GMT的时间差,和UTC还是有些区别的)

  32. 小鱼儿说道:

    谢谢旭哥的指点啊
    还有一问,如果我这样写

    else{
    pms.sec = ″束″;
    pms.mini = ″结″;
    pms.hour = ″经″;
    pms.day = ″已″;
    pms.month = ″购″;
    pms.year = ″团″;
    }

    这样不起作用呢,怎么解决呢?是我写的不对吗?
    再谢旭哥!

  33. 小鱼儿说道:

    旭哥,我要等多久才能等到你的回复啊
    可怜我是个js白痴

    • 张 鑫旭说道:

      @小鱼儿
      Date.UTC(2030, 6, 27); 其中6不是表示6月份,而是7月份,是要加1的。所以你的到期其实还有一个月时间。

  34. 小鱼儿说道:

    @ 团团,可以多次调用,但是你要用不同的 id 才可以

    我现在更期待旭哥能解决一下月份一定要加1的问题,以及我上面的问题

  35. 小鱼儿说道:

    不好意思,原谅我要刷屏了。最新发现!
    var d = Date.UTC(2010, 12, 22, 0, 0);
    这种情况下else不起作用,仍然从29开始倒计时

    var d = Date.UTC(2010, 11, 22, 0, 0);
    这种情况下else不起作用,成功!

    旭哥,due>0的判断是否有问题啊
    您可以用我上面两个数据试试看。
    期待指点啊~~~

  36. 小鱼儿说道:

    还是我,现在起作用了
    但是同一个页面中多次调用,只有一个起作用,另外一个还是显示29天(多次调用,用的不同的id)

  37. 小鱼儿说道:

    if(dur > 0){
    pms.sec = f.zero(dur % 60);
    pms.mini = Math.floor((dur / 60)) > 0? f.zero(Math.floor((dur / 60)) % 60) : “00”;
    pms.hour = Math.floor((dur / 3600)) > 0? f.zero(Math.floor((dur / 3600)) % 24) : “00”;
    pms.day = Math.floor((dur / 86400)) > 0? f.zero(Math.floor((dur / 86400)) % 30) : “00”;
    //月份,以实际平均每月秒数计算
    pms.month = Math.floor((dur / 2629744)) > 0? f.zero(Math.floor((dur / 2629744)) % 12) : “00”;
    //年份,按按回归年365天5时48分46秒算
    pms.year = Math.floor((dur / 31556926)) > 0? Math.floor((dur / 31556926)) : “0”;
    }
    else{
    pms.sec = “8”;
    pms.mini = “8”;
    pms.hour = “8”;
    pms.day = “8”;
    pms.month = “8”;
    pms.year = “8”;
    }
    return pms;

    ——————————–

    我是这样修改的,如果时间到期,就显示8天8小时8分8秒

    但修改后,JS貌似不起作用,仍然变成29天…….

  38. 小鱼儿说道:

    如果时间到期
    那么日会自动变成29
    这个问题怎么解决呢?
    亲爱的张大哥,帮忙解决一下吧

  39. 一样的问题说道:

    倒计时结束以后 天就会自动变成29,期待解决!

  40. 小鱼儿说道:

    如果时间到期
    那么日会自动变成29
    这个问题怎么解决呢?
    亲爱的张大哥,帮忙解决一下吧
    最好可以实现这个功能,到期后,自动显示“已经到期”几个字样。那样就完美了。呵呵
    期待答复啊

  41. Gyrate说道:

    哇,我觉得脚本代码的写法可读性相当高,很不错。 同一页面至于多次调用的问题,我是用闭包解决的

  42. 团团说道:

    不能多次调用
    有什么办法可以在一个页面里面显示多个不同的倒计时呢?

  43. rqyy说道:

    能在倒计时结束后触发一个动作吗?

    • 张 鑫旭说道:

      可以的,原脚本只有if(dur > 0){}的判断,如果时间结束,则dur为为0,所以,在后面加个else{…}就是倒计时结束触发的动作了。

  44. 小脑说道:

    帅哥~为什么月份要减一个月才能正常显示当月呢 不能不减一个月吗~~

  45. viajes-a-china说道:

    谢谢了。。。不错嘛

  46. 百度优化说道:

    我以前也有研究这方面的

  47. 康康说道:

    啊,不让贴,那就麻烦您说一下这种用法的名字吧,谢谢啦,我经常在jQuery的插件里看到类似的用法,麻烦了!

  48. 康康说道:

    new document

    全部贴上了,希望能方便您排错,我第一次用这种变量 = { a:b,c:d… }这样的格式,希望能说出这个用法的名字,我好自己找些资料,谢谢啊!