1

I'm using Sigma.Js library and want to make the graph rotate around its axis for the first 10 seconds after the page loads. I wrote the following code for it, but it doesn't work. Any idea why?

 for (i = 0; i < 101; i++) {

    var angle = i / 100;
    s.cameras[0].angle = angle;

    setTimeout(function() {
       s.refresh();
    },100);

 }

FYI s refers to the graph initialized, s.cameras[0].angle sets the angle of the view (referring to it through console works, so that's correct), s.refresh reloads the graph.

I guess it has something to do with async (the cycle gets executed bypassing timeout?), but can't figure it out myself...

Thank you for your help!

Aerodynamika
  • 7,883
  • 16
  • 78
  • 137

2 Answers2

4

All of the timeouts are set at the same time, so having a timeout of 100ms will cause all of them to fire at the same time.

Set your timeout to 100*i, so the timeouts are then staggered as 100, 200, 300, ... 10100.

You may also run into scope issues with the i variable, so wrap it in a closure like this:

for (i = 0; i < 101; i++) {
  setTimeout((function(i) {
    return function() {
      var angle = i / 100;
      s.cameras[0].angle = angle;
      s.refresh();
    };
  })(i), 100*i);
}

An cleaner syntax (for IE9+) is:

for (i = 0; i < 101; i++) {
  setTimeout(function(i) {
    var angle = i / 100;
    s.cameras[0].angle = angle;
    s.refresh();
  }.bind(void 0,i), 100*i);
}

For information about why you need to do that, see this reference answer: Javascript infamous Loop issue?

Community
  • 1
  • 1
000
  • 26,951
  • 10
  • 71
  • 101
  • Great, thank you so much! And do you know how I can make it rotate infinitely and in the smoothest way possible? Right now it kind of jumps. BTW I can't accept the answer because of the time limit - will do it in 3 mins :) – Aerodynamika May 22 '14 at 21:03
  • 1
    Do it like this: http://stackoverflow.com/questions/22154129/javascript-settimeout-loops and set `var angle = (i / 100) % (Math.PI*2);` – 000 May 22 '14 at 21:04
1

You are setting 101 timeouts in a loop, but by the time the first one even executes, you have already finished all the times through the loop and set the final angle. So you have two problems. One, as pointed out by Joe Frambach, your timeouts are all set to go off (near)-simultaneously-- each one is going to execute 100ms after it is set, not 100ms after the last one. Two, none of the timeouts, when they go off, change the angle. They all just do what I assume is refreshing the view...thus they will all show the same, final angle which was already all done being set by the time the first refresh is called.

Consider something more like this:

var currentIteration = 0;
var interval = setInterval(
    function()
    {
        if(currentIteration > 100)
            clearInterval(interval);
        else
        {
            s.cameras[0].angle = currentIteration / 100;
            s.refresh();
            currentIteration++;
        }
    },
    100);
tmcgill
  • 76
  • 5