Fehler im Script bei wiederholtem Funktionsaufruf
Ralf
- dhtml
Hallo
ich möchte mit DHMTL ein Div per Tastatur (Pfeiltasten) steuern. Um nicht noch eine fats identische Funktion schreiben zu müssen möchte ich die aufgerufene Funktion nach einem setTimeout erneut aufrufen ihr aber diesmal einen Parameter übergeben. Beispiel:
function moving(k) {
if(window.event.keyCode == 38 || k == 38)
{
guy.style.top = (guy.offsetTop - steps);
window.setTimeout("moving(38)", 1000);
}
}
Jedoch wird nach einer einer Sekunde ein Fehler verursacht. IE (6.0) meldet dann "Objekt erforderlich". Woran mag das liegen!?
Ich habe es auch schon mit 2 Funktionen versucht die fats identisch sind, wobei die eine Funktion jedoch die andere aufruft und umgekehrt. Dort hat es funktioniert :|
hier mein Quellcode
<html>
<head>
<title>Test</title>
<script language="Javascript" type="text/jscript">
<!--
var guy;
var guyX = 150, guyY = 150;
var steps = 1;
var speed = 100;
function moving(k) {
guy = eval(document.getElementById("Guy"));
guy.style.position = "absolute";
if(window.event.keyCode == 38 || k == 38)
{
guy.style.top = (guy.offsetTop - steps);
window.setTimeout("moving(38)", speed);
}
if(window.event.keyCode == 40 || k == 38)
{
guy.style.top = (guy.offsetTop + steps);
window.setTimeout("moving(40)", speed);
}
if(window.event.keyCode == 37 || k == 37)
{
guy.style.left = (guy.offsetLeft - steps);
window.setTimeout("moving(37)", speed);
}
if(window.event.keyCode == 39 || k == 38)
{
guy.style.left = (guy.offsetLeft + steps);
window.setTimeout("moving(39)", speed);
}
}
document.onkeydown = moving;
//-->
</script>
</head>
<body>
<div id="Guy" style="width:50px;height:50px;background:#ff8800"></div>
</body>
</html>
Desweiteren interessieren mich noch 2 Dinge:
1. Warum geht es nicht bei der Zeile mit "document.onkeydown = moving;", wenn ich den Funktionsaufruf moving mit einer klammer abschliesse? Sprich
document.onkeydown = moving();
2. Als ich es vorhin mit den 2 Funktionen getestet hatte und dabei das Div mit den Pfeiltasten in verschiedene richtungen steuerte, war bemerkbar, dass logischerweise die sich ständig wieder aufrufenden funktionen sich stets addiert haben. dabei haben ich nenne es mal "verschiedene Kräfte" aufeinander gewirkt die das Div zum rütteln brachten. Wie könnte ich (wenn ich die Richtung ändere) vorhergehende setTimeout() abbrechen. Gibt es noch eine Möglichkeit die setTimeouts irgendwie zu benennen oder zu finden damit ich später sagen kann "wenn ich nach rechts steuere, brich mir alle setTimeouts ab denen ich den Parameter 37 übergeben habe?!
Danke schonmal für eure (evtl) Hilfe :)
hi,
Jedoch wird nach einer einer Sekunde ein Fehler verursacht. IE (6.0) meldet dann "Objekt erforderlich". Woran mag das liegen!?
ich vermute folgendes:
document.onkeydown = moving;
damit sorgst du dafür, dass die funktion beim (runter)drücken einer taste aufgerufen wird.
function moving(k) {
if(window.event.keyCode == 38 || k == 38)
da die funktion durch einen event ausgelöst wurde, gibt es bei diesem ersten aufruf window.event.keyCode.
window.setTimeout("moving(38)", 1000);
bei diesem aufruf denke ich aber, ist window.event.keyCode gar nicht existent, da die funktion jetzt nicht durch einen event ausgelöst wurde, sondern durch setTimeout.
gruss,
wahsaga
und
guy = eval(document.getElementById("Guy"));
das eval ist hier überflüssig und vor allem macht er das Skript merklich langsamer. Merke: eval ist evil.
Da du aber sowieso nur einen Layer verwendest, würd ich das aus der Funkiton rausnehmen und guy global definieren, da auch getElementBy relativ langsam sein kann.
guy.style.position = "absolute";
Das reicht einmal, bzw. besser gleich im CSS.
Desweiteren interessieren mich noch 2 Dinge:
- Warum geht es nicht bei der Zeile mit "document.onkeydown = moving;", wenn ich den Funktionsaufruf moving mit einer klammer abschliesse? Sprich
document.onkeydown = moving();
weil du so die Funktion moving aufrufst und den rückgabewert and den Event übergibst.
Mach einfach mal:
alert(moving)
und dann
alert(moving())
und du merkst den Unterschied
- Als ich es vorhin mit den 2 Funktionen getestet hatte und dabei das Div mit den Pfeiltasten in verschiedene richtungen steuerte, war bemerkbar, dass logischerweise die sich ständig wieder aufrufenden funktionen sich stets addiert haben. dabei haben ich nenne es mal "verschiedene Kräfte" aufeinander gewirkt die das Div zum rütteln brachten. Wie könnte ich (wenn ich die Richtung ändere) vorhergehende setTimeout() abbrechen. Gibt es noch eine Möglichkeit die setTimeouts irgendwie zu benennen oder zu finden damit ich später sagen kann "wenn ich nach rechts steuere, brich mir alle setTimeouts ab denen ich den Parameter 37 übergeben habe?!
Ich würd mal sagen dein Konzept ist nicht ganz sauber. Du solltest einfach eine globale Funktion move() erstellen, die den Layer bewegt und in welche Richtung wird bestimmt durch globale x/y Werte die durch den key event geändert wedern.
Also in etwa so (ungetester quickhack)
var isMove = false;
var d_x = 0; // horizontal
var d_y = 0; // vertikal
var obj = null;
var speed = 100;
function move()
{
if(!isMove || !obj) return;
obj.style.top = obj.offsetTop + d_x;
obj.style.left = guy.offsetLeft + d_y;
setTimeout('move()', speed);
}
Stattdessen könnte man hier auch setInterval anwenden (in der Funktion start())
function start()
{
obj = document.getElementById("Guy");
if(!obj) return;
move();
}
function keyDown(evt)
{
if(window.event.keyCode == 38) d_y = -1; // hoch
if(window.event.keyCode == 40) d_y = 1; // runter
if(window.event.keyCode == 37 ) d_x = -1; // links
if(window.event.keyCode == 39) d_x = 1; // rechts
}
Da liesse sich noch leicht der Mozilla Event einbauen, dann brauchst du noch eine Stop Funktion.
Struppi.