Javascript 倒计时问题

发布于 2024-11-03 14:38:07 字数 3060 浏览 1 评论 0原文

好吧,我正在尝试为这里看到的每个挑战重新创建倒计时: http://www.bungie.net/stats/reach/globalchallenges.aspx

问题是,如果您将我的倒计时原始倒计时大约有10-14秒的差异,我只是不明白为什么?谢谢!

我正在使用他们的移动页面(查看源代码)中的源代码来获取过期时间。

<span id="wExpSeconds" title="1304330400000"></span>
<span id="dExpMilliseconds" title="1303984800000"></span>

这是我的倒计时页面的源代码:

<html>
    <head>
        <title></title>
        <style type="text/css">
        .stat{ font: 14px/18px Arial, Helvetica, sans-serif; color:#bbb; }
        .seconds{ color:#ff5f3c; }
        </style>
    </head>
    <body>

        <div id="countDownDiv"></div>

        <script type="text/javascript">
        function countDown(id, end, cur){
            this.container = document.getElementById(id);
            this.endDate = new Date(end);
            this.curDate = new Date(cur);


            var context = this;

            var formatResults = function(day, hour, minute, second){
            var displayString = [
                '<span class="stat">',day,'d </span>',
                '<span class="stat">',hour,'h </span>',
                '<span class="stat">',minute,'m </span>',
                '<span class="stat seconds">',second,'s</span>'
            ];
            return displayString.join("");
            }

            var update = function(){
                context.curDate.setSeconds(context.curDate.getSeconds()+1);

                var timediff = (context.endDate-context.curDate)/1000; 

                // Check if timer expired:
                if (timediff<0){ 
                    return context.container.innerHTML = formatResults(0,0,0,0);
                }

                var oneMinute=60; //minute unit in seconds
                var oneHour=60*60; //hour unit in seconds
                var oneDay=60*60*24; //day unit in seconds

                var dayfield=Math.floor(timediff/oneDay);
                var hourfield=Math.floor((timediff-dayfield*oneDay)/oneHour);
                var minutefield=Math.floor((timediff-dayfield*oneDay-hourfield*oneHour)/oneMinute);
                var secondfield=Math.floor((timediff-dayfield*oneDay-hourfield*oneHour-minutefield*oneMinute));

                context.container.innerHTML = formatResults(dayfield, hourfield, minutefield, secondfield);

                // Call recursively
                setTimeout(update, 1000);
            };

            // Call the recursive loop
            update();
            }

        countDown("countDownDiv",1304330400000, new Date().getTime());
        </script>
    </body>
</html>

Well I'm trying to recreate the countdown for each of these challenges seen here:
http://www.bungie.net/stats/reach/globalchallenges.aspx

The problem is if you compare my countdown with the original countdown there is about a 10-14 second difference, I just don't understand why? Thanks!

I'm using the source from their mobile page(view source) to get the expiration times.

<span id="wExpSeconds" title="1304330400000"></span>
<span id="dExpMilliseconds" title="1303984800000"></span>

Here is the source code of my countdown page:

<html>
    <head>
        <title></title>
        <style type="text/css">
        .stat{ font: 14px/18px Arial, Helvetica, sans-serif; color:#bbb; }
        .seconds{ color:#ff5f3c; }
        </style>
    </head>
    <body>

        <div id="countDownDiv"></div>

        <script type="text/javascript">
        function countDown(id, end, cur){
            this.container = document.getElementById(id);
            this.endDate = new Date(end);
            this.curDate = new Date(cur);


            var context = this;

            var formatResults = function(day, hour, minute, second){
            var displayString = [
                '<span class="stat">',day,'d </span>',
                '<span class="stat">',hour,'h </span>',
                '<span class="stat">',minute,'m </span>',
                '<span class="stat seconds">',second,'s</span>'
            ];
            return displayString.join("");
            }

            var update = function(){
                context.curDate.setSeconds(context.curDate.getSeconds()+1);

                var timediff = (context.endDate-context.curDate)/1000; 

                // Check if timer expired:
                if (timediff<0){ 
                    return context.container.innerHTML = formatResults(0,0,0,0);
                }

                var oneMinute=60; //minute unit in seconds
                var oneHour=60*60; //hour unit in seconds
                var oneDay=60*60*24; //day unit in seconds

                var dayfield=Math.floor(timediff/oneDay);
                var hourfield=Math.floor((timediff-dayfield*oneDay)/oneHour);
                var minutefield=Math.floor((timediff-dayfield*oneDay-hourfield*oneHour)/oneMinute);
                var secondfield=Math.floor((timediff-dayfield*oneDay-hourfield*oneHour-minutefield*oneMinute));

                context.container.innerHTML = formatResults(dayfield, hourfield, minutefield, secondfield);

                // Call recursively
                setTimeout(update, 1000);
            };

            // Call the recursive loop
            update();
            }

        countDown("countDownDiv",1304330400000, new Date().getTime());
        </script>
    </body>
</html>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

深空失忆 2024-11-10 14:38:07
   <script type="text/javascript">
    function countDown(id, end, cur){
        this.container = document.getElementById(id);
        this.endDate = new Date(end);
        this.curDate = new Date(cur);

由于该函数不是作为任何对象的方法来调用,也不是通过 call() 或 apply() 来调用,因此它的 this 关键字将引用全局对象。因此,上面有效地为容器、endDate 和 curDate 创建了全局变量。

        var context = this;

请写出 1,000 遍:this 关键字不是上下文(也与范围无关)。

         ...
         context.curDate.setSeconds(context.curDate.getSeconds()+1);

正如已经讨论过的,变量“context”是对全局对象的引用,它是由调用函数的方式设置的。所以你在这里访问全局变量。

         ...
         // Call recursively
         setTimeout(update, 1000);

这是你的问题。这将在大约 1 秒内调用更新。计数器运行的时间越长,它就会变得越不准确(它总是会稍后漂移)。

您应该每次都获取一个新的日期对象,查看毫秒,然后在下一个整秒之后调用下一个超时(给它大约 30 到 50 毫秒以确保它是在之后而不是之前)。这样你的计数器就永远不会偏离太多,即使偏离太多,它也会在每次调用时自行纠正。

并确保每次都计算完整的倒计时,因此如果有几秒钟的延迟,您会再次赶上。

   <script type="text/javascript">
    function countDown(id, end, cur){
        this.container = document.getElementById(id);
        this.endDate = new Date(end);
        this.curDate = new Date(cur);

Since the function is not called as a method of any object, nor with call() or apply(), its this keyword will reference the global object. So the above effectively creates global variables for container, endDate and curDate.

        var context = this;

Please write out 1,000 times: the this keyword is not context (nor does it have anything to do with scope).

         ...
         context.curDate.setSeconds(context.curDate.getSeconds()+1);

As already discussed, the variable "context" is a reference to the global object, it is set by how you call the function. So you are accessing global variables here.

         ...
         // Call recursively
         setTimeout(update, 1000);

Here is your problem. That will call update in about 1 second. The longer your counter runs, the more inaccurate it will become (it will always drift later).

You should get a new date object each time, look at the ms, then call the next timeout just after the next full second (give it about 30 to 50ms to make sure it's just after and not before). That way your counter will never be out by much and even if it is, it will correct itself each time it is called.

And make sure you calculate the full count down each time, so if there is a lag of a few seconds you catch up again.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文