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>
4

1 に答える 1

0
   <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()orを使用してもapply()、その this キーワードはグローバル オブジェクトを参照します。したがって、上記はコンテナ、endDate、および curDate のグローバル変数を効果的に作成します。

        var context = this;

1,000 回書き出してください: this キーワードはコンテキストではありません(スコープとも関係ありません)。

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

既に説明したように、変数 "context" はグローバル オブジェクトへの参照であり、関数の呼び出し方法によって設定されます。したがって、ここでグローバル変数にアクセスしています。

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

これがあなたの問題です。これにより、約1 秒で update が呼び出されます。カウンターが長く実行されるほど、不正確になります (常に後でドリフトします)。

毎回新しい日付オブジェクトを取得し、ミリ秒を見て、次の 1 秒の直後に次のタイムアウトを呼び出す必要があります (約 30 ~ 50 ミリ秒を指定して、直前ではなく直後であることを確認してください)。そうすれば、カウンターが大きく外れることはなく、たとえそうであっても、呼び出されるたびに自動的に修正されます。

そして、毎回完全なカウントダウンを計算するようにしてください。数秒の遅れがある場合は、再び追いつくようにしてください.

于 2011-04-28T03:34:25.370 に答える