9

I am trying to cause a block to "pulsate" between 100% opacity and some partially transparent opacity. I want to do this with the functionality that is built into the jQuery core, if possible. I would rather not add a plugin to get this effect. Here is the code that i am trying to use:

    $(document).ready(function() {
 function pulsate() {
  $("#pulsating-block").animate({opacity: 0.2}, 3000).animate({opacity: 1}, 3000, null, function() {pulsate()});
 }
 pulsate();  });

The problem is that each time the animation completes, it pauses for about a second before looping again. How can I keep it from pausing so that I get a smooth "pulsating" effect? (Note: the animation is exaggerated in this example to highlight the problem that I am having)

Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
Tim Mackey
  • 323
  • 3
  • 16
  • I've tried the code and I don't see a pause in the animation at all. Is it just me? Are you running on a slow machine or an old browser? – brianpeiris Jan 29 '10 at 20:18
  • I'm running on an Quad-Core G5, so I don't think its a speed issue :-), and I've tried this in both Firefox and Safari (most recent versions). I'm also using v1.4.1 of jQuery, which is the most recent version. Try making the duration shorter, it might help to see what I'm talking about. Here's a diagram how it is appearing to me: \\\\\/////----\\\\\\/////---- ( "\" = fade out, "/" fade in, "-" = no change in opacity) – Tim Mackey Jan 29 '10 at 21:12

2 Answers2

11

Perhaps your issue is with the "swing" easing function jQuery uses by default.

You might want to try the "linear" easing function instead:

$(document).ready(function() {
  function pulsate() {
    $("#pulsating-block").
      animate({opacity: 0.2}, 3000, 'linear').
      animate({opacity: 1}, 3000, 'linear', pulsate);
  }
  pulsate();
});

I've also coded up a small pulsate plugin that includes a "bounce" easing function that may be more to your liking. I should note that the plugin uses a continuous calculation to perform the animation, not two separate fade-in/fade-out animations, so it might help with the "pause" issue. (To be honest, I still don't see the pause you are talking about.)

Working Demo

http://jsbin.com/isicu (editable via http://jsbin.com/isicu/edit)

Full Source

JavaScript

(function ($) {
  $.fn.pulsate = function (properties, duration, type, speed, callback) {
    type = type || 'Swing'
    speed = speed || 'Normal';
    this.animate(properties, duration, 'pulsate' + type + speed, callback);
  };

  function createPulsateLinear (speed) {
    speed *= 2;
    return function (p, n) {
      return (Math.asin(Math.sin(Math.PI * n / speed)) + Math.PI / 2) / Math.PI;
    }
  }

  function createPulsateSwing (speed) {
    return function (p, n) {
      return (1 + Math.sin(n / speed)) / 2;
    }
  }

  function createPulsateBounce (speed) {
    speed *= 2;
    return function (p, n) {
      return (
        ((Math.asin(Math.sin(Math.PI * n / speed)) + Math.PI / 2) / Math.PI) *
        (Math.sin(Math.PI * n / speed) + 1) / -2 + 1
      );
    }
  }

  var speeds = {
    fast: 100,
    normal: 200,
    slow: 400
  }

  $.extend(jQuery.easing, {
    pulsateLinearFast: createPulsateLinear(speeds.fast),
    pulsateLinearNormal: createPulsateLinear(speeds.normal),
    pulsateLinearSlow: createPulsateLinear(speeds.slow),
    pulsateSwingFast: createPulsateSwing(speeds.fast),
    pulsateSwingNormal: createPulsateSwing(speeds.normal),
    pulsateSwingSlow: createPulsateSwing(speeds.slow),
    pulsateBounceFast: createPulsateBounce(speeds.fast),
    pulsateBounceNormal: createPulsateBounce(speeds.normal),
    pulsateBounceSlow: createPulsateBounce(speeds.slow)
  });
})(jQuery);

$(document).ready(function() {
  var
    pulsatingBlocks = $('.pulsating-block'),
    forever = 5 * 24 * 60 * 60 * 1000; // 5 days! (Which is forever in Internet time)

  pulsatingBlocks.filter('.opacity').each(function () {
    $(this).pulsate({opacity: 0.2}, forever, this.className.split(' ')[0], 'Slow');
  });

  pulsatingBlocks.filter('.top').each(function () {
    $(this).pulsate({top: 100}, forever, this.className.split(' ')[0], 'Slow');
  });

});

HTML

<!DOCTYPE html>
<html>
<head>
<script class="jsbin" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.js"></script>
<meta charset=utf-8 />
<title>Pulsate</title>
<style>
  div { clear: left; margin-bottom: 2em; }
  .pulsating-block {
    width: 6em; height: 4em;
    margin: 0.5em; margin-right: 10em;
    float: left; clear: none; position: relative;
    background: lightblue;
    text-align: center;
    padding-top: 2em;
    font: bold 1em sans-serif;
  }
</style>
</head>
<body>
  <div>
    <div class="Linear opacity pulsating-block">linear</div>
    <div class="Swing opacity pulsating-block">swing</div>
    <div class="Bounce opacity pulsating-block">bounce</div>
  </div>
  <div>
    <div class="Linear top pulsating-block"></div>
    <div class="Swing top pulsating-block"></div>
    <div class="Bounce top pulsating-block"></div>
  </div>
</body>
</html>
brianpeiris
  • 10,735
  • 1
  • 31
  • 44
  • Thanks, Brian! Your function is exactly what I was trying to reach in the end. I wasn't sure how to write the code so that it could handle more than just opacity, but this does it! I'm a little embarrassed...It turns out that the problem I was seeing had nothing to do with the code, but rather with my monitor calibration(!). The example I was using was a black block fading in and out on a white background. My monitor was clipping off the lower range of blacks, and that made it look as if the animation stopped momentarily. Doh! Thank you, though, this script is exactly what I needed. Fantastic! – Tim Mackey Feb 01 '10 at 19:02
  • Glad I could help. I figured the problem was more visual than technical. Good job noticing that it was your monitor, that is one obscure "bug" :P – brianpeiris Feb 01 '10 at 21:39
  • 1
    That could be one of the single most complete answers I've ever seen for any question here. Your demo was terrific. – Scott Stafford Nov 16 '10 at 16:30
0

try

 function pulsate() {
      $("#pulsating-block").animate({opacity: 0.2}, 3000,function(){
          $(this).animate({opacity: 1}, 3000, null, function() {pulsate()});
      });
     }
Funky Dude
  • 3,867
  • 2
  • 23
  • 33
  • Thanks for the quick reply! Unfortunately, that doesn't seem to fix the problem I'm having. (You might be able to see the problem better if you reduce the duration to 500 milliseconds) The problem is that after returning to 100% opacity, the animation seems to stall before it begins to dim the duration again. The element stays at 100% opacity for about half or a whole second before it starts dimming again. It doesn't seem to pause at 20% opacity (which is how I want it to work). – Tim Mackey Jan 29 '10 at 19:27