2016-07-08 17 views
1

Ich benutze setInterval, um eine Funktion aufzurufen, die ein Fraktal auf einem HTML5-Canvas animiert. Es gibt auch einen Schieberegler, mit dem der Benutzer die Qualität des Fraktals ändern kann. Alles funktioniert gut, bis ich anfange, den Schieberegler zu ändern. Wenn ich es ändere, wird die fraktale Animation abgehackt, und schließlich wird die Funktion "drawFractal" nicht mehr aufgerufen. Hier ist der Schieber HTML:Javascript setInterval wird nach dem Zufallsprinzip gestoppt

<input type="range" id="qualitySlider" min="1" max="10"></input> 

Hier ist die Javascript (es erzeugt nur ein Fraktal):

var count = 0.5; 

var slider = document.getElementById("qualitySlider"); 
var g = document.getElementById("drawingCanvas").getContext("2d"); 

function drawFractal() { 
    var cellSize = Math.ceil(slider.value); 
    //canvas is 700 by 400 
    g.fillStyle = "black"; 
    g.clearRect(0, 0, 700, 400); 

    //Eveything from here to the end of this function generates the fractal 
    var imagC = Math.cos(count)*0.8; 
    var realC = Math.sin(count)*0.5; 
    for (x = 0; x < 700; x+=cellSize) { 
     for (y = 0; y < 400; y+=cellSize) { 
      var yCoord = (x/700.0 - 0.5)*3; 
      var xCoord = (y/400.0 - 0.5)*3; 
      var real = xCoord; 
      var imag = yCoord; 

      var broken = 0; 
      for (i = 0; i < 8; i++) { 
       var temp = real*real - imag*imag + realC; 
       imag = 2*imag*real + imagC; 
       real = temp; 
       if (real*real + imag*imag >= 4) { 
        broken = true; 
        break; 
       } 
      } 

      if (!broken) { 
       g.fillRect(x, y, cellSize, cellSize); 
      } 
     } 
    } 
    count = count + 0.04; 
} 

setInterval(drawFractal, 60); 

Ich brauche nur die "drawFractal" Funktion zuverlässig alle 60 Millisekunden aufgerufen werden.

+4

Verwenden Sie 'requestAnimationFrame'. Safari ist berüchtigt für das Überspringen von Timer-Events. –

+3

Sind Sie sicher, dass Sie diese Funktion in weniger als 60 ms ausführen können? Ihre innerste "for" -Schleife wird jedes Mal, wenn sie aufgerufen wird, bis zu 2,2 Millionen Mal (700 * 400 * 8) ausgeführt. Ich frage mich, ob der Browser gerade die Vergeblichkeit erkennt, alle 60ms aufzurufen, wenn es nicht in weniger als das abgeschlossen wird. – jfriend00

+0

Ein rekursives setTimeout ist möglicherweise ein besserer Ansatz, wenn die Methode länger als das festgelegte Intervall dauern könnte, um den Animationsrahmen noch besser anzufordern. – ste2425

Antwort

-2

Sie verwenden setInterval() um drawFractal alle 60 ms aufzurufen, und dann jedes Mal, wenn drawFractal ausgeführt wird, rufen Sie setInterval() erneut auf, was unnötig ist. Sie haben jetzt zwei Timer, die versuchen, Fraktale alle 60 ms zu zeichnen ... dann haben Sie 4, dann 8 usw.

Sie müssen entweder (1) setInterval() einmal zu Beginn der Programmausführung aufrufen und Rufen Sie es nicht erneut auf oder (2) wechseln Sie zu setTimeout() und rufen Sie es am Ende jedes drawFractal() auf.

Ich würde die zweite Option verwenden, nur für den Fall, dass Ihr Fraktal dauert mehr als 60 ms zu zeichnen.

+0

Dies ist nicht was passiert. –

0

Dies ist mein verbesserter Code. Ich habe gerade requestAnimationFrame verwendet, um die Funktion "drawFractal" rekursiv aufzurufen. Mit der Funktion setTimeout habe ich auch die Animation auf 24 Bilder/Sek. Beschränkt.

var count = 0.5; 

var qualitySlider = document.getElementById("qualitySlider"); 
var g = document.getElementById("drawingCanvas").getContext("2d"); 

function drawFractal() { 
    var cellSize = Math.ceil(qualitySlider.value); 
    //canvas is 700 by 400 
    g.fillStyle = "black"; 
    g.clearRect(0, 0, 700, 400); 
    var imagC = Math.cos(count)*0.8; 
    var realC = Math.sin(count)*0.5; 
    for (x = 0; x < 700; x+=cellSize) { 
     for (y = 0; y < 400; y+=cellSize) { 
      var yCoord = (x/700.0 - 0.5)*3; 
      var xCoord = (y/400.0 - 0.5)*3; 
      var real = xCoord; 
      var imag = yCoord; 

      var broken = 0; 
      for (i = 0; i < 8; i++) { 
       var temp = real*real - imag*imag + realC; 
       imag = 2*imag*real + imagC; 
       real = temp; 
       if (real*real + imag*imag >= 4) { 
        broken = true; 
        break; 
       } 
      } 

      if (!broken) { 
       g.fillRect(x, y, cellSize, cellSize); 
      } 
     } 
    } 
    count = count + 0.04; 
    setTimeout(function() { 
     requestAnimationFrame(drawFractal); 
    }, 41); 
} 

drawFractal(); 
Verwandte Themen