0

I am trying to animate some elements on a page using JavaScript (CSS animations with sprites will not work for what I need to do).

I am currently doing something like this;

function animate_element(current_id)
{
    var next_id = parseInt(current_id, 10) + 1;
    $('#lighthouse')[0].src = '/element_' + next_id + '.png';

    if (next_id >= 8) {
        next_id = 0;
    }     

    setTimeout(function() {
        animate_element(next_id);
    }, 750);
}

Technically this works, but this is going to be one of many animations on the page that will be doing something similar and I am worried this is an inefficient way of doing it.

I know best practice is to use clearTimeout() before calling setTimeout, but I don't know how to record the setTimeout and recursively pass it into itself (if that makes any sense!).

Any guidance on the best practice way of doing this would be much appreciated.

1
  • 1
    That code looks alright as is. setTimeout is plenty "efficient", in that it doesn't waste any CPU cycles or tie up anything else. I'd say your fine. Commented Oct 30, 2012 at 21:35

3 Answers 3

2

"I know best practice is to use clearTimeout() before calling setTimeout..."

For what you're doing, there's no reason to call clearTimeout() since the next call will never happen until the last one has been executed.

At that point, there's nothing to clear.


FWIW, your code can be shortened a bit:

function animate_element(current_id) {
    current_id = parseInt(current_id, 10);

    function cycle() {
        document.getElementById('lighthouse').src = '/element_' + current_id + '.png';
        current_id = ++current_id % 8
        setTimeout(cycle, 750);
    }
}

animate_element(0);

Or if there are several that are the same, just with a different ID, you can make it reusable like this:

function animate_element(id, idx) {
    idx = parseInt(idx, 10);

    function cycle() {
        document.getElementById(id).src = '/element_' + idx + '.png';
        idx = ++idx % 8
        setTimeout(cycle, 750);
    }
}

animate_element('lighthouse', 0);
Sign up to request clarification or add additional context in comments.

Comments

1

Didn't look closely at your code, or what you're doing, but if you want to keep the value, you can close over the variable:

var animate_element = (function(){

   var timer;

   return function(current_id)
   {
       var next_id = parseInt(current_id, 10) + 1;
       $('#lighthouse')[0].src = '/element_' + next_id + '.png';

       if (next_id >= 8) {
           next_id = 0;
       }     

       clearTimeout(timer);
       timer = setTimeout(function() {
          animate_element(next_id);
       }, 750);
   };

})();

Comments

1

I'd say setInterval would be better over setTimeout in your case.

var current_id = 0;

function animate_element() {
  setInterval(function() {
    var next_id = parseInt(current_id, 10) + 1;
    $('#lighthouse')[0].src = '/element_' + next_id + '.png';

    if (next_id >= 8) {
        next_id = 0;
    }

    current_id = next_id;
  }, 750);
}

2 Comments

What is the benefit of doing it this way?
If you're calling the same function at the end of each timeout, you're actually creating an interval. To save yourself from clearing and calling the timeout, you may as well just use the setInterval() function which was made for that exact purpose.

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.