David Tunnell
David Tunnell

Reputation: 7542

Looping div animations

I am trying to get a div to continually animate:

$(document).ready(function() {
  function arrowmovement() {
    setTimeout(function() {
      $("#downarrowimg").animate({
        'margin-top': "-=30px"
      });
    }, 500);
    setTimeout(function() {
      $("#downarrowimg").animate({
        'margin-top': "+=30px"
      });
    }, 500);
  }
  arrowmovement();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="downarrow">
  <img id="downarrowimg" src="https://upload.wikimedia.org/wikipedia/en/f/f1/Down_Arrow_Icon.png">
</div>

It is only running one time. What am I doing wrong and how do I fix it?

Upvotes: 1

Views: 100

Answers (9)

Karthik Mahadevaiah
Karthik Mahadevaiah

Reputation: 51

This is simple to understand.

$(document).ready(function (argument) {
     var operator = '-'; 
     setInterval(arrowMovement,500);
     function arrowMovement() { 
        if(operator == '-') { 
             operator = '+' 
        }  else { 
             operator = '-' 
        } 

        $('#downarrow').animate({'margin-top':operator+10}, 500);  
     } 
 });

Upvotes: 0

DavidDomain
DavidDomain

Reputation: 15293

You can use the complete function of the animate method and you do not really need a timeout here.
A pure CSS animation like Rounin suggested would be an option as well.

.animate()

complete Type: Function() A function to call once the animation is complete, called once per matched element.

Here is an example.

$( document ).ready(function() {
    function arrowmovement() {
        var d = ($( "#downarrowimg" ).css('margin-top') === "-30px") ?  "+" : "-";
        $( "#downarrowimg" ).animate({
            'margin-top' : d + "=30px"
        }, 500, // duration
	function() { // complete fn
            arrowmovement();
        });
    }
    arrowmovement();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div id="downarrow">
  <img id="downarrowimg" src="https://upload.wikimedia.org/wikipedia/en/f/f1/Down_Arrow_Icon.png">
</div>

Upvotes: 1

tao
tao

Reputation: 90103

$(document).ready(function() {
  function arrowUp() {
    $("#downarrowing").animate(
    	{'margin-top': "-=30px"}, 600, function(){arrowDown()});
  }

  function arrowDown() {
  	$("#downarrowing").animate(
    	{'margin-top': "+=30px"}, 600, function(){arrowUp()});
  }
	arrowUp();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <img id="downarrowing" src="https://upload.wikimedia.org/wikipedia/en/f/f1/Down_Arrow_Icon.png">
</div>

Upvotes: 1

louisbros
louisbros

Reputation: 875

You could just call the arrowmovement function at the end of each animation:

function arrowmovement(direction) {
    $("#downarrowimg").animate({
        'margin-top': "+="+ (30 * direction) +"px"
    }, 500, function() {
        arrowmovement(direction * -1);
    });
}

$(document).ready(function() {
    arrowmovement(1);
});

Demo: https://jsfiddle.net/louisbros/dhwoejon/

Upvotes: 0

Rounin
Rounin

Reputation: 29463

Here's a pure CSS solution which animates #downarrow continuously:

@keyframes downarrowanimation {
    0% {margin-top: 30px;}
    50% {margin-top: -30px;}
    100% {margin-top: 30px;}
}

#downarrow {
    animation: downarrowanimation 1s ease-in-out infinite;
}
<div id="downarrow">
<img id="downarrowimg" src="https://upload.wikimedia.org/wikipedia/en/f/f1/Down_Arrow_Icon.png">
</div>

Upvotes: 3

Tyler Sebastian
Tyler Sebastian

Reputation: 9458

Why don't you just use CSS? You get all niceness with the added benefit of the animation being GPU accelerated.

@keyframes bounce {
  from {margin-top: 30px;}
  to {margin-top: -30px;}
}

.arrow {
  animation-name: bounce;
  animation-duration: 1s;
  animation-direction: alternate;
  animation-iteration-count: infinite;
}
<div id="downarrow">
      <img class="arrow" src="https://upload.wikimedia.org/wikipedia/en/f/f1/Down_Arrow_Icon.png">
    </div>

Upvotes: 0

Zakaria Acharki
Zakaria Acharki

Reputation: 67505

There's several ways to do that, i suggest to use setInterval(), check the example bellow.

Hope this helps.


var down=true;

setInterval(function() {
  if( down ){
      $( "#downarrowimg" ).animate({
        'margin-top' : "-=30px"
      }, function() {
        down=false;
      });
  }else{
    $( "#downarrowimg" ).animate({
        'margin-top' : "+=30px"
    }, function() {
        down=true;
    });
  }
},500);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="downarrow">
  <img id="downarrowimg" src="https://upload.wikimedia.org/wikipedia/en/f/f1/Down_Arrow_Icon.png">
</div>

Upvotes: 1

G-Cyrillus
G-Cyrillus

Reputation: 105923

you need to use setInterval().

$(document).ready(function() {
  var repeatIt = setInterval(arrowmovement, 1000);
  function arrowmovement() {
    setTimeout(function() {
      $("#downarrowimg").animate({
        'margin-top': "-=30px"
      });
    }, 500);
    setTimeout(function() {
      $("#downarrowimg").animate({
        'margin-top': "+=30px"
      });
    }, 500);
  }

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="downarrow">
  <img id="downarrowimg" src="https://upload.wikimedia.org/wikipedia/en/f/f1/Down_Arrow_Icon.png">
</div>

set it in a var so you can stop it :

function abortTimer() { // to be called when you want to stop the timer
  clearInterval(repeatIt);
}

Upvotes: 0

jered
jered

Reputation: 11581

jQuery is really bad at animation. The Greensock Animation Package (GSAP) is a fantastic and lightweight animation library you could look into instead.

TweenMax.to($("div"), .5, {y: "+=50", ease: Linear.easeNone, yoyo: true, repeat: -1});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.1/TweenMax.min.js"></script>
<div style="width: 50px; height: 50px; background-color: red;"></div>

One line does all you need. If you want more complex easing, use the TimelineMax class to chain together animations.

var timeline = new TimelineMax({repeat: -1});
timeline.to($("div"), .5, {y: "+=50", ease: Power2.easeOut});
timeline.to($("div"), .5, {y: "-=50", ease: Power2.easeOut});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.1/TweenMax.min.js"></script>
<div style="width: 50px; height: 50px; background-color: red;"></div>

Upvotes: -1

Related Questions