Reputation: 1041
I'm trying to write a function to slowly move an image around the screen. The relevant html is as follows:
var dom, timer;
function initImage() {
dom = document.getElementById('animate').style;
dom.position = 'absolute';
dom.top = "165px";
dom.left = "767px";
regulate(1115,165);
regulate(1115,540);
regulate(767,540);
regulate(767, 165);
}
function regulate(xfinal, yfinal) {
var timer = setInterval(function() {moveImage(xfinal,yfinal)}, 1);
return true;
}
function moveImage(xfinal, yfinal) {
var x = parseInt(dom.left.match(/\d+/));
var y = parseInt(dom.top.match(/\d+/));
if ((x == xfinal) && (y== yfinal)) {clearInterval(timer);}
else {
if (x != xfinal) {
if (x < xfinal) {x++;}
else {x--;};
dom.left = x + "px";}
else {
if (y < yfinal) {y++;}
else {y--;};
dom.top = y + "px";};
};
return true;
}
<img src='http://placehold.it/200' alt='Sir Victor' width=50 height=50
id='animate' onload='initImage();' style='position:absolute;'/>
This algorithm works fine for the first function call to regulate(), but when I uncomment one of the other three and try to run it, the image either doesn't move at all, or it moves faster than normal, but only along the first path. Is there some reason the function won't act as expected the second time?
I'm new to javascript, so feel free to point out anything else that seems dumb or over-complicated as well.
Upvotes: 0
Views: 900
Reputation: 20633
Instead of calling all the regulate
functions at once; set up a queue.
var dom;
var timer;
var queueIndex = 0;
var positions = [
[300, 0],
[300, 100],
[0, 100],
[0, 0]
];
function initImage() {
dom = document.getElementById('animate').style;
dom.position = 'absolute';
dom.top = "0px";
dom.left = "0px";
regulate.apply(null, positions[queueIndex]);
}
function regulate(xfinal, yfinal) {
timer = setInterval(moveImage, 1, xfinal, yfinal);
return true;
}
function moveImage(xfinal, yfinal) {
var x = parseInt(/\d+/.exec(dom.left) || 0);
var y = parseInt(/\d+/.exec(dom.top) || 0);
if ((x == xfinal) && (y == yfinal)) {
clearInterval(timer);
queueIndex++;
if (positions[queueIndex]) {
regulate.apply(null, positions[queueIndex]);
}
} else {
if (x != xfinal) {
if (x < xfinal) {
x++;
} else {
x--;
};
dom.left = x + "px";
} else {
if (y < yfinal) {
y++;
} else {
y--;
};
dom.top = y + "px";
};
};
return true;
}
<img src='https://libcom.org/files/images/library/black-square.jpg' alt='Sir Victor' width=50 height=50 id='animate' onload='initImage();' style='position:absolute;' />
Upvotes: 0
Reputation: 707158
One problem is that you can't pass the contents of the timer
variable to setInterval()
in this line:
var timer = setInterval(moveImage, 1, xfinal, yfinal, timer);
because the value of timer
is not available until after setInterval()
returns.
Thus, you will just be passing undefined
for that value so your clearInterval()
in moveImage()
will not work properly.
The usual way to solve this problem is to declare the timer
variable in some higher level shared scope so it will be available as needed.
Upvotes: 2