Javascript rotation animation

23,350

Solution 1

There are a couple of steps to solve your problem:

An ID in HTML cannot start with a number, so rename them to something like 'hair1', 'hair2', etc.

The main problem is that because of the setInterval, by the time the function runs, i will not be the i that you were expecting. This is because of variable scope. You can get around this with an anonymous function.

Combining both of the above gives this code:

<div class="hair" onclick="rotate()">
  <img src="single.png" id="hair1" width="10" height="40">
  <img src="single.png" id="hair2" width="10" height="40">
  <!-- etc -->
</div>

// NOTE: This is not the final code listing, see below for a final answer. 
for (var i = i; i < 11; i++) {
  (function(local_i) {
    setInterval(function () {
      // use local_i instead of i inside this function for the results you expect
      document.getElementById('hair' + local_i).style.WebkitTransitionDuration='1s';
      document.getElementById('hair' + local_i).style.webkitTransform = 'rotate(40deg)';
    }, 100);
  })(i);
}

I would also recommend putting the styles into a stylesheet, then apply them using a class:

.rotate
{
  -webkit-transform: rotate(40deg);
  -webkit-transition: -webkit-transform 1s;
}

Finally, to get the elements to rotate in a row rather than all together, you need to multiply the interval by the value of i. I think that you probably mean to use setTimeout rather than setInterval (setInterval will keep running over and over again).

function rotate(){
  for(var i=1;i<11;i++) {
    (function (local_i) {
      setTimeout(function(){
        document.getElementById('hair' + local_i).classList.add('rotate');
      }, 100 * local_i);
    })(i);
  }
}

I've put together a demo here

Solution 2

You're encountering the classic scope/closure/reference problem most people run into when using anonymous functions. I've answered this question a while back, and provided tons of info on what is actually happening (Ignore the first paragraph of my answer, the rest of the answer is applicable, though). Meanwhile, the answer to your problem is:

for(var i=1;i<11;i++)
{
    setInterval((function(myI)
    {
        return function()
        {
            document.getElementById(myI).style.WebkitTransitionDuration='1s';
            document.getElementById(myI).style.webkitTransform = 'rotate(40deg)';
        };
    }(i)),100);
}

Be aware that you're setting intervals: the callback will be called every 100ms as long as the browser window remains open.
You're not storing the interval id anywhere, so I'd either use setTimeout or create a (preferably non-global) array of id's so you can do clearInterval(intervalID[x]); when you need to.

Share:
23,350
Admin
Author by

Admin

Updated on June 04, 2020

Comments

  • Admin
    Admin almost 4 years

    I am stuck at a point.There are 10 straight lines(png image).What I want is after the first line rotates by 40 deg,then the second line should start its rotaion and then the third,fourth,fifth and so on!!!

    code:

    <div class="hair" onclick="rotate()">
        <img src="single.png" id="1" width="10" height="40">
        <img src="single.png" id="2" width="10" height="40">
        <img src="single.png" id="3" width="10" height="40">
        <img src="single.png" id="4" width="10" height="40">
        <img src="single.png" id="5" width="10" height="40">
        <img src="single.png" id="6" width="10" height="40">
        <img src="single.png" id="7" width="10" height="40">
        <img src="single.png" id="8" width="10" height="40">
        <img src="single.png" id="9" width="10" height="40">
        <img src="single.png" id="10" width="10" height="40">
    </div>
    

    Javascript:

    function rotate(){
        for(var i=1;i<11;i++)
        {
            setInterval(function(){
                document.getElementById(i).style.WebkitTransitionDuration="1s";
                document.getElementById(i).style.webkitTransform = 'rotate(40deg)';
            },100)
        }
    }
    
  • Admin
    Admin almost 11 years
    but the animation is not there,all the lines are rotating at the same time,which is something that i dont want. This is what i want l l l l l l l l l l---initial position / l l l l l l l l l ---1st animation / / l l l l l l l l ---2nd animation / / / l l l l l l l ---3rd animation and so on.
  • Elias Van Ootegem
    Elias Van Ootegem almost 11 years
    @jayeshjain: your animation is set to take +- 1 second, yet the interval is .1 of a second. Of course they'll all appear to rotate together. Furthermore. the 10th id will rotate ~10 times faster by the end of the first second... trust me: increase the interval (from 100 to 5000 or something to get a better view of things), and use an IIFE
  • Admin
    Admin almost 11 years
    I have already tried that,but the second line starts animating before the first line has ended its animation. And whats iife
  • Harsha Venkatram
    Harsha Venkatram almost 11 years
    The demo doesn't work.All the divs rotate at once which is not what the OP wants
  • iblamefish
    iblamefish almost 11 years
    @harsha no they don't - the final code listing rotates each one in 100ms intervals. Check out the demo.
  • Harsha Venkatram
    Harsha Venkatram almost 11 years
    The reason why I said it doesn't work is because I saw the demo and it didn't work.
  • Elias Van Ootegem
    Elias Van Ootegem almost 11 years
    @jayeshjain: Read the linked answer to find out more about IIFE's (Immediatly Invoked Function Expression). Also: the intervals won't slow the foreach loop down one bit, you know... just make a callback sequence (queue) from within your first interval callback. setup a fiddle, and I'll take a look at it after lunch if needs must
  • iblamefish
    iblamefish almost 11 years
    @jayeshjain in the demo I used index instead of local_i - sorry for the confusion - I'll update the demo code now! Classlist is like an array that contains all of the classes of an element that lets you easily add and remove classes. More information on classlist