0

the site is here I'm trying to create an animated button by moving the position of the background using Javascript when the user clicks the button. However, instead of slowly scrolling, the button jumps to the end of the loop. Here's the code:

var x=1, y=0, z=1;

function animate () {
    document.getElementById("switch").style.backgroundPosition = y + 'px 0px';
}

function toggle() {
    // check if button is on
    if (x==1) {
        //As long as image is not yet in place, move the background
        while (y>-37) {
            //Delay each move by 500 and increase the delay
            setTimeout("animate()",500*z);
            --y;++z;
        }
        --x;
        //reset increasing timer
        z=1;
    }
    // check if button is off
    else if (x==0) {
        //As long as image is not yet in place, move the background
        while (y<0) {
            //Delay each move by 500 and increase the delay
            setTimeout("animate()",500*z);
            ++y;++z;
        }
        ++x;
        //reset increasing timer
        z=1;
    }
}

Please let me know how to fix. Thanks!

4
  • 2
    When the animate() is called the first time (by setTimeout), the while loop already finished and y will have "end value" (e.g. -37). If you provide a simplified jsfiddle.net example, I would be more inclined to help you ;) But the basic idea would be to not start the timeouts all at once but each call creates a new timeout... something like that. Commented Apr 27, 2011 at 22:30
  • Ok, signing up for jsfiddle.net. Commented Apr 27, 2011 at 22:44
  • Here's the jsfiddle: jsfiddle.net/UrBestFriend/26PfR Commented Apr 27, 2011 at 22:48
  • 1
    jsfiddle.net/wambotron/8JhkU Try something like this. BTW your timeout earlier would've made this animation excruciatingly slow. Commented Apr 27, 2011 at 23:21

2 Answers 2

3

This works:

var on = true,
    sw = document.getElementById("switch"),
    stop, y = 0,
    dir, to;

function animate() {
    sw.style.backgroundPosition = y + 'px 0px';
    y += dir;
    if (y != stop) {
        to = setTimeout(animate,25);
    }
}

function toggle() {
    if (to) {
        clearTimeout(to);
    }
    if (on) {
        dir = -1;
        stop = -38;
    }
    else {
        dir = 1;
        stop = 2;

    }
    to = setTimeout(animate, 25);
    on = !on;
}

DEMO

Don't know if it is the best way though.

Note: You either have to run the code in the body.onload event handler or put it at the bottom of the page.

You can also try to play with the step size and the timeout time.... there was something else I wanted to say, but I forgot ;)

Another note: You should always use expressive variable names. E.g. It was not clear that x is used as a boolean indicator (at least not if you only have a quick lock at it).

Sign up to request clarification or add additional context in comments.

2 Comments

Definitely follow the advice on var names.
Thanks! I switched y += dir; and sw.style.backgroundPosition = y + 'px 0px'; position so that there won't be an initial bounce when the function is triggered.
1

The setTimeout function doesn't pause, it just arranges to execute the function (its first argument) after the specified delay and then immediately returns. So, launching a whole bunch of timeouts isn't that useful. You want the setTimeout callback to call setTimeout to start another timer. And you can use a function rather than a string as the first argument to setTimeout.

2 Comments

This is only part of the problem as the the timeout gets increased in every iteration. So would the function that is called in setTimeout not depend on a variable that is modified in the loop it would work...
@Felix: True but you got your jsfiddle and sorted it all out before I got back here. So, +1 for you.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.