2012-04-18 22 views
5

Jak wspomniano w tytule, próbuję utworzyć metronom oparty na jQuery/JavaScript wraz z tagiem HTML <audio />, aby odtworzyć dźwięk.HTML5/jQuery metronome - problemy z wydajnością

Działa "w porządku", ale wydaje mi się, że metoda setInterval nie działa wystarczająco dokładnie. Przeszukałem niektóre wątki tutaj, ale jestem nowy zarówno w jQuery, jak i JavaScript i nie znalazłem działającego rozwiązania. To samo dotyczy "otwartej nowej karty i setInterval zatrzymuje się lub opóźnia" - problem. Próbowałem temu zapobiec z stop(true,true), ale nie działało, jak się spodziewałem.

Chcę, aby metronom działał "w tle" bez zmiany tempa podczas otwierania nowej karty i robienia czegoś tam. Chcę również dokładny metronom na pewno;)

Oto moje środowisko testowe położone: http://nie-wieder.net/metronom/test.html

Obecnie kod JS i HTML-markup są w źródle test.html, więc można tam zajrzeć .

Również tutaj jest zaniepokojony (jak myślę) JS-kod używam:

$(document).ready(function() { 

    //vars 
    var intervalReference = 0; 
    var currentCount  = 1;  
    var countIncrement  = .5;  
    var smin = 10; 
    var smax =240; 
    var svalue = 120; 

    //soundchkbox 
    $(".sndchck").attr("disabled", true); 

    //preload sound 
    $.ajax({ 
     url: "snd/tick.ogg", 
     success: function() { 
      $(".sndchck").removeAttr("disabled"); 
     } 
    }); 

    // tick event 
    var met = $("#bpm").slider({ 
      value: 120, 
      min: smin, 
      max: smax, 
      step: 1, 
      change: function(event, ui) { 
       var delay = (1000*60/ui.value)/2 
       clearInterval(intervalReference); 

       //seems to be the Problem for me 
       intervalReference = setInterval(function(){ 
        var $cur_sd = $('#sub_div_'+currentCount); 
        $cur_sd 
        .stop(true,true) 
        .animate({opacity: 1},15, 
           function() { 
           //Play HTML5 Sound 
           if($('#sound_check:checked').val()){ 
            $('#tick') 
            .stop(true,true) 
            .trigger("play"); 
           } 
            $(this). 
            stop(true,true). 
            animate({opacity:0}); 
           } 
        ); 
        currentCount += countIncrement; 
        if(currentCount > 4.5) currentCount = 1 
       }, delay); 
       createMusicTag(ui); 
      } 
     }); 
}); 

Każda pomoc będzie wielki, jestem z pomysłów na teraz.

Odpowiedz

5

setInterval nie jest dokładny. co można spróbować zrobić coś takiego jak:

var timestamp = (new Date()).getTime(); 
function run() { 

    var now = (new Date()).getTime(); 

    if(now - timestamp >= 1000) { 
     console.log('tick'); 
     timestamp = now; 
    } 

    setTimeout(run, 10); 
} 
run(); 

To będzie (co setnej sekundy) porównanie „timestamp” z bieżącego czasu aby sprawdzić, czy edycja jest drugą lub więcej (odchylenie wynosi 0,01 sekundy) i jeśli jest to logi "tick" i resetuje bieżący timestamp.

http://jsfiddle.net/rlemon/UqbwT/

Jest to najlepsze podejście do czegoś, co musi być dokładny czas (IMO).

Aktualizacja: jeśli zmienisz ustawienie czasu setTimeout ... otrzymasz mniejsze odchylenie. http://jsfiddle.net/rlemon/UqbwT/1/

Druga aktualizacja: Po przejrzeniu tego posta, pomyślałem, że musi być dokładniejszy sposób używania timerów w javascript .. więc przy odrobinie badań natknąłem się na artykuł this. Sugeruję, żebyś to przeczytał.

+0

Przede wszystkim dziękuję za bardzo szybką odpowiedź. Zaktualizowałem twoje skrzypce tutaj: http://jsfiddle.net/ping/UqbwT/3/, aby sprawdzić, czy Twoje podejście działa dla mnie. Wydaje się, że tak nie jest, przynajmniej na moim macbooku (firefox 11). A może po pewnym czasie widzę te opóźnienia? (tick pokazuje> 600 lub> 700 przez jakiś czas). – Dominik

+0

może być problem z implementacją. ale w zasadzie ten pomysł wciąż jest prawdziwy. Nie można polegać na funkcjach czasowych przeglądarki. nie są dokładne, a Ty ** dostrzeżesz odchylenie. Zamiast tego chcesz uruchomić stałą pętlę w tle, patrząc na prawdziwą datę i godzinę i używając jej do określenia, czy minęła sekunda. – rlemon

+0

Tak, masz rację, dziękuję za odpowiedź. Myślę, że będę kontynuować twoje rozwiązanie i utworzę aplikację java lub coś dla ludzi, którzy chcą "więcej";) Dziękuję bardzo. Przynajmniej masz rację, to jest problem z wdrożeniem i myślę, że nie mogę zrobić o wiele więcej. – Dominik

Powiązane problemy