stoper jQuery, opóźnienie - interval

0

Witam!
Chciał bym zrobić stoper offline przy użyciu jQuery z dokładnością do milisekund.
i oczywiście, zbyt fajnie by było gdyby było wszystko ok. Pojawia się opóźnienie... dlaczego?

(function($){
    $.fn.stopWatch = function(settings) {

        var config = {
        'hour': 0,
        'minute': 0,
        'second': 0,
        'mili': 0,
        'setInterval': false
        };
        if(settings)
        {
            $.extend(config,settings);
        }
        return this.each(function()
        {
            var timer = $(
            '<div id="stopwatch-timer">'
            + '<span id="stopwatch-h">00</span>'
            + '<span>:</span>'
            + '<span id="stopwatch-m">00</span>'
            + '<span>:</span>'
            + '<span id="stopwatch-s">00</span>'
            + '<span>:</span>'
            + '<span id="stopwatch-mili">000</span>'
            + '</div>');
            
            var controls = $(
            '<div id="stopwatch-controls">'
            + '<button id="start"><i></i> start</button>'
            + '<button id="stop" ><i></i> stop</button>'
            + '<button id="reset"><i></i> reset</button>'
            + '</div>');
            
            $(this).append(timer, controls);
            
            var stopWatch = function()
            {
                if(config.mili < 999)
                {
                    config.mili++;
                    if(config.mili < 10)
                    {
                        $('#stopwatch-mili').html('00'+config.mili);
                    }
                    else 
                    if(config.mili >= 10 && config.mili<100)
                    {
                        $('#stopwatch-mili').html('0'+config.mili);
                    }
                    else
                    {
                        $('#stopwatch-mili').html(config.mili);
                    }
                }
                else if(config.mili == 999)
                {
                    config.mili = '000';
                    $('#stopwatch-mili').html(config.mili);
                    if(config.second <59)
                    {
                        config.second++;
                        if (config.second < 10) 
                        {
                            $('#stopwatch-s').html('0' + config.second);
                        } 
                        else 
                        {
                            $('#stopwatch-s').html(config.second);
                        }
                    }                
                    else if (config.second == 59) 
                    {
                        config.second = '00';
                        $('#stopwatch-s').html(config.second);
                        if (config.minute < 59) 
                        {
                            config.minute++;
                            if (config.minute < 10) 
                            {
                                $('#stopwatch-m').html('0' + config.minute);
                            } 
                            else 
                            {
                                $('#stopwatch-m').html(config.minute);
                            }
                        }
                        else if (config.minute == 59) 
                        {
                            config.minute = "00";
                            $('#stopwatch-m').html(config.minute);
                            if (config.hour < 24) 
                            {
                                config.hour++;
                                if (config.hour < 10) 
                                {
                                    $('#stopwatch-h').html('0' + config.hour);
                                } 
                                else 
                                {
                                    $('#stopwatch-h').html(config.hour);
                                }
                            }
                            else if (config.hour == 24) 
                            {
                                config.hour = "00";
                                $('#stopwatch-h').html(config.hour);
                            }
                        }
                    }
                }
        }//end stopwatch
$('#start').bind(
    {
    click: function() 
        {
        config.setInterval = self.setInterval
        (
            function(){stopWatch()},1
        );
    $('#start').attr("disabled","disabled");
}
});
// click on stop
$('#stop').bind({
    click: function() {
        config.setInterval = window.clearInterval(config.setInterval);
        $('#start').removeAttr("disabled");
    }
});
// click on reset
$('#reset').bind({
    click: function() {
        config.hour = 0;
        $('#stopwatch-h').html('00');
        config.minute = 0;
        $('#stopwatch-m').html('00');
        config.second = 0;
        $('#stopwatch-s').html('00');
        config.mili = 0;
        $('#stopwatch-mili').html('000');
    }
});
});
};
})(jQuery);

Z góry dziękuje za pomoc i rady.
Pozdrawiam.

1

Jak tak spojrzałem to przypomniał mi się jeden post od Ferrante o jQuery. Że często lepiej skorzystać z czystego JSa niż ułatwiać sobie jQuery (co sam robie ciągle xd), bo jQuery nie zawsze ma genialnie rozwiązane te funkcje. No i wpisałem z ciekawości jaka jest różnica między setInterval z jQuery i setTimeout z JS. Odpowiedź masz tutaj: http://stackoverflow.com/questions/729921/settimeout-or-setinterval

Spróbuj zrobić to samo z setTimeoutem. Bardzo możliwe, że wtedy będzie chodzić w porządku. Różnica jest subtelna, ale w tym przypadku ważna. Bo to, że tam element się pojawia po sekundzie z odsetkami można pominąć. Ale timer musi być dokładny.

0

Właściwie, to znalazłem własnie podobną odpowiedź... A chciałem użyć jquery jako, że już i tak miałem go zaimplementowanego... zły pomysł jak widać. Teraz przerabiam lekko skrypt na pobieranie czasu .now i odejmowaniu od pobranego przy kliknięciu stop, a wyświetlenie będzie szło swoim rytmem... napisze jak skończę;) chyba, ze uważacie, ze to zły pomysł?

1

Wiesz co, ostatecznie poda Ci dobry wynik, ale bardzo profesjonalnie to nie będzie działać. Potem w zależnosci od tego jak burzliwie będzie skrypt działał na czyimś komputerze, będzie tą różnicę bardziej lub mniej widać. No ale na pewno jest to jakis półśrodek. Ja np. robiłem na uczelnie układ cyfrowy, timer do mierzenia czasu ułożenia Kostki Rubika. I z funkcją delay (tak na początku kombinowałem) wychodziły mi czasy po 7 sekund regularnie :P A to w moim przypadku tak na serio się zdarzyło może raz w życiu. Także lepiej jednak wymyślać takie algorytmy, które są niezależne od wydajności komputera tak samo zgodne z rzeczywistym upływem czasu.

0

No właśnie o tym mówię:

  1. pobieram czas.start przy kliknięciu start
  2. funkcja z interval np 10 pobiera czas.teraz i odejmuje od czas.start
  3. wynik wyświetla co te 10+(czas an wykonanie funkcji) ale będzie to stała różnica.
    Hm? Będzie chyba lepiej ;)
1

Po pierwsze:
http://stackoverflow.com/questions/1127905/how-can-i-format-an-integer-to-a-specific-length-in-javascript

Po drugie:
setInterval i setTimeout są z założenia niedokładne. setInterval używasz do wyświetlania czasu stopera co około 50-100milisekund, a samo mierzenie wykonuj używając:
var start = Date.now();
var aktualnyczas = Date.now() - start; // czas w milisekundach

var milisekundy = aktualnyczas; // wyswietlasz: (milisekundy % 1000)
var sekundy = milisekundy / 1000; // wyswietlasz: (sekundy % 60)
var minuty = sekundy / 60; // wyswietlasz: (minuty % 60)
var godziny = minuty / 60; // wyswietlasz: godziny (chyba, ze chcesz doby dodac to % 24)

0

I tak też zrobiłem:)

(function($){
    $.fn.stopWatch2 = function(settings) 
    {
        var data = new Date();
        var config =
        {
            'date':0,
            'year': 0,
            'month': 0,
            'day': 0,
            'hour': 0,
            'minute': 0,
            'second': 0,
            'mili': 0,
            'setInterval': false
        };
        var czas_startu = 
        {
            'date':0,
            'year': 0,
            'month':0,
            'day': 0,
            'hour': 0,
            'minute': 0,
            'second': 0,
            'mili': 0,  
        }
        if(settings)
        {
            $.extend(config,settings);
        }
        return this.each(function()
        {
            
            var timer = $(
            '<div id="stopwatch-timer">'
            + '<span id="stopwatch-h">00</span>'
            + '<span>:</span>'
            + '<span id="stopwatch-m">00</span>'
            + '<span>:</span>'
            + '<span id="stopwatch-s">00</span>'
            + '<span>:</span>'
            + '<span id="stopwatch-mili">000</span>'
            + '</div>');
            
            var controls = $(
            '<div id="stopwatch-controls">'
            + '<button id="start"><i></i> start</button>'
            + '</div>');
            
            $(this).append(timer, controls);

            var porownanie = function()
            {
                var data = new Date(config.date - czas_startu.date);
                var mili = data.getMilliseconds();
                var sec = data.getSeconds();
                var min = data.getMinutes();
                var h = data.getHours()-1;
                var d = data.getDay()-4;
                var m = data.getMonth();
                var y = data.getYear()-70;
                //$('#stopwatch-mil').html('0' + config.second);
                //console.log(y+' '+m+' '+d+' '+h+' '+min+' '+sec+' '+mili);
                if(mili<10)
                $('#stopwatch-mili').html('00'+mili);
                else if(mili>=10 && mili<100)
                $('#stopwatch-mili').html('0'+mili);
                else 
                $('#stopwatch-mili').html(mili);
                
                if(sec<10)
                $('#stopwatch-s').html('0'+sec);
                else
                $('#stopwatch-s').html(sec);
                
                if(min<10)
                $('#stopwatch-m').html('0'+min);
                else
                $('#stopwatch-m').html(min);
                
                if(h<10)
                $('#stopwatch-h').html('0'+h);
                else
                $('#stopwatch-h').html(h); 
                
            }
            var czas_ustaw = function()
            {
                var data = new Date();
                config.date = data;
                config.year = data.getFullYear();
                config.month = data.getMonth();
                config.day = data.getDate();
                config.hour = data.getHours();
                config.minute = data.getMinutes();
                config.second = data.getSeconds();
                config.mili = data.getMilliseconds();   
            }
            var stopWatch2 = function()
            {
                czas_ustaw();
                porownanie();
            }//end stopwatch
            
$('#start').bind
(
    {
    click: function() 
        {
            //var teraz = new Date();
            var data = new Date();
            czas_startu.date = data;
            czas_startu.year = data.getFullYear();
            czas_startu.month = data.getMonth();
            czas_startu.day = data.getDate();
            czas_startu.hour = data.getHours();
            czas_startu.minute = data.getMinutes();
            czas_startu.second = data.getSeconds();
            czas_startu.mili = data.getMilliseconds();            
            config.setInterval = self.setInterval
            (
                function(){stopWatch2()},50
            );

            jQuery(this).removeAttr("id").attr("id","stop");
        }
    }
);
// click on stop

});
};
})(jQuery);

Jak zwykle pomocni - rozdaje plusiki i pozdrawiam ;)

0

ode mnie info - pamiętaj, że funkcje czasowe w javascript mogą mieć ustawiony minimalny czas przez przeglądarki. tj. np. na windowsie masz nawet w ustawieniach zasilania minimalny interwał w przypadku gdy laptop pracuje na zasilaniu bateryjnym - mniejszy interwał spowoduje że i tak będzie użyty ten minimalny. chrome robi podobnie w przypadku zakładek które są nieużywane - im dłużej nie używasz karty - tym wydłuża się minimum. tak na przyszłość pamiętaj, a gdy będzie to krytyczne to poszukaj informacji o tym (ja też mam informacje tylko "po łebkach", którymi się dzielę)

1 użytkowników online, w tym zalogowanych: 0, gości: 1