0

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.

3
  • can you provide this code in plunkr ? Commented May 13, 2015 at 3:03
  • You need to place timer within the global scope as well (given you're referencing it in both moveImage and regulate. (May not be THE issue, but it's at least AN issue. Commented May 13, 2015 at 3:05
  • you are passing timer variable before it is assigned a value! Commented May 13, 2015 at 3:10

2 Answers 2

2

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.

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

Comments

0

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;' />

1 Comment

I made the edits you suggested, still not getting the expected result.

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.