Fipsel: jQuery Problem

Beitrag lesen

ich möchte per jQuery ein Element ein anderes verfolgen lassen. Dazu habe ich folgende Funktion:

while($("#zwei").offset().left>$("#drei").offset().left)

{
$("#drei").css('left','+=5');
}

  

> Ändere ich es nun aber so ab:  
> ~~~javascript

while($("#zwei").offset().left>$("#drei").offset().left)  

> 	{  
> 		$("#drei").animate({"left": "+=5px"}, "fast");  
> 	}

Dann fährt der Block ins endlose weiter bzw das Script stürzt ab.

Bei animate() gibst du das Ziel der Animation an. Benutzt du einen Zielwert, der relativ zum aktuellen Wert liegt, dann wird das Ziel vermutlich deshalb nie erreicht, weil es bei jedem Animationsschritt immer wieder fünf Pixel (in deinem Beispiel) vom jeweils aktuellen Wert (Animationsschritt, nicht Ziel!) entfernt ist. Das Ganze passiert innerhalb der animate()-Schleife.

Der Unterschied zu deiner ersten Fassung ist, dass dort nur einmal der neue Wert berechnet wird. Dann fragst du in der while-Bedingung die Position wieder ab und setzt erneut einmalig.

Deine zweite Konstruktion ist deshalb auch unsinnig, denn im Grunde erstellst du zweimal dieselbe Animation erstellst. Einmal bewegst du um Fünf-Pixel-Schritte in animate(), zusätzlich bewegst du um Fünf-Pixel-Schritte in der while()-Schleife. Eins von beiden reicht: Entweder nimmst du die while-Schrittschleife mit css() und Fünf-Pixel-Schritten. Oder du übergibst animate() den tatsächlichen Zielwert, d.h. die tatsächliche Position von #zwei und keine Fünf-Pixel-Schritte dorthin.

Davon unabhängig ist deine Konstruktion einer sogenannten busy loop ganz pfuibäh - und das schon seit Jahrzehnten. Du verbrätst dauerhaft maximale Prozessorleistung, nur um die meiste Zeit festzustellen, dass nichts zu tun ist.

Anstatt tausendmal pro Sekunde nutzlos deine Schleife zu durchlaufen, frage zumindest lieber mit setTimeout() in angemessenen Abständen, zum Beispiel alle halbe Sekunde, die Koordinaten ab. Hat sich was geändert, führe einmal die Animation aus. Benutze danach erneut setTimeout(). In etwa so:

var verfolgen = function (igel, hase, reaktionszeit) {  
	var igel = $(igel),  
		hase = $(hase);  
	  
	var intervall = function () {  
        window.setTimeout(bewegen, reaktionszeit);  
    };  
  
    var bewegen = function () {  
		console.debug(igel, hase, reaktionszeit);  
	    var links = igel.offset().left;  
        if (links > hase.offset().left) {  
            hase.animate({"left": links}, {"duration": "fast", "complete": intervall});  
        }  
        else {  
            intervall();  
        };  
	};  
	  
	intervall();  
};  
  
$(document).ready(function () {  
	verfolgen("#zwei", "#drei", 500);  
});

Hast du ein Ereignis, an dass du die Bewegung knüpfen kannst, nutzes dieses statt der regelmäßigen Abfragen.