jQuery Problem
jsproblem
- javascript
Moin,
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');
}
Solange das eine Element weiter links ist als das andere, soll es nach links verschoben werden. Führt man nun diese Seite im Browser aus, sind beide Elemente bereits auf einer höhe (das heißt, dass die Funktion funktioniert hat).
Ändere ich es nun aber so ab:
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.
Ich möchte aber eine Animation haben und nicht einfach die Elemente übereinander setzen.
Hat jemande einen Tipp? Oder gibt es alternative Lösungen zur Elementverfolgung in JS/jQuery?
MfG
while($("#zwei").offset().left>$("#drei").offset().left)
{
$("#drei").animate({"left": "+=5px"}, "fast");
}
Führe dir einmal vor Augen, was animate macht. Es startet eine Animation, bei welcher mit setTimeout alle paar Millisekunden eine Funktion aufgerufen wird, die den left-Wert um einen Schritt erhöht.
Wenn du nun in einer Schleife wieder und wieder Animationen startest, so speicht jQuery die m.W. einfach intern in der Animations-Queue, die nach und nach abgearbeitet wird.
Wahrscheinlich hattest du vor, eine Endlosschleife zu programmieren, die ständig läuft und die Werte überwacht. Das kannst du in JavaScript nicht tun, damit hängst du nur den Browser auf.
JavaScript funktioniert Event-basiert, es gibt aber keinen Event, der gefuert wird, sobald sich ein Element bewegt. Daher musst du die Problemstellung vereinfachen: Es gibt doch einen Grund, warum #zwei sich bewegt? Vermutlich wegen eines JavaScripts. An der richtigen Stelle dieses Scripts kannst du #drei so animieren, dass es #zwei folgt.
Andernfalls müsstest du regelmäßig prüfen, ob sich #zwei bewegt hat. Das kannst du mit setTimeout oder setInterval tun. Etwa so:
<http://jsfiddle.net/K7LbQ/>
Wie gesagt, das ist natürlich gestellt, man könnte die Überprüfung auch einfach dort ausführen, wo #zwei verschoben wird, anstatt nachträglich mit setTimeout zu prüfen.
Mathias
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.