7

I've created a jQuery function that scrolls a DIV by decreasing the left-margin of the element. It works, but it's incredibly slow. It eats up 100% CPU in no time :s

$(".scroll").hover(
    function () {
        var scroll_offset = parseInt($('#content').css('margin-left'));
        sliderInt = self.setInterval(function(){
            $content.css({'margin-left':scroll_offset+'px'});
            scroll_offset--;
        },8);
    }, 
    function () {
        clearInterval(sliderInt);
    }
);

Obviously I am running this function every 8ms, which is asking a lot. I'm already cacheing my selectors, so I don't know what I can do to improve performance. Am I just going about it the wrong way?

Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
thv20
  • 986
  • 4
  • 13
  • 26
  • 2
    That's the state of animation with JavaScript. One thing you can do is lower the "frame rate". jQuery's default is 13ms per "frame". I'd suggest going to at least 75ms. – Brad Apr 18 '12 at 23:39
  • 1
    also, consider using `requestAnimationFrame` and as fallback `setTimeout` instead of `setInterval`. Article including a Shim for this -> http://paulirish.com/2011/requestanimationframe-for-smart-animating/ – GNi33 Apr 18 '12 at 23:48

2 Answers2

24

function play () {
  $('#ball').animate({left: '+=20'}, 100, 'linear', play);
}

function pause () {
  $('#ball').stop();
}

$("#bar").hover( play, pause );
#bar {
  margin-top: 20px;
  background: #444;
  height: 20px;
}
#bar:hover #ball {
  background: lightgreen;
}

#ball {
  position: relative;
  left: 0;
  width: 20px;
  height: 20px;
  background: red;
  border-radius: 50%;
}
<div id="bar">
  <div id="ball"></div>
</div>

<script src="//code.jquery.com/jquery-3.1.0.js"></script>

This is really simple without the setInterval or even setTimeout.

  • The only important thing is to know that .animate() accepts a function callback, ideal for our purpose to create loop a function. Make sure to use the linear easing instead of the default 'swing' to make our loop constant.
  • To stop our animations we can use stop() to prevent animation buildups.
  • Simply create 2 functions and use them in your hover method.

Using CSS3

and toggling play/pause classes using jQuery:

function play() {
  $('#ball').addClass("play").removeClass("pause");
}

function pause() {
  $('#ball').addClass("pause"); // don't remove .play here
}

$("#bar").hover(play, pause);
#bar {
  margin-top: 20px;
  background: #444;
  height: 20px;
}
#bar:hover #ball {
  background: lightgreen;
}
#ball {
  position: relative;
  left: 0;
  width: 20px;
  height: 20px;
  background: red;
  border-radius: 50%;
}

.play {
  animation: ball-anim 5s infinite linear;
}
.pause {
  animation-play-state: paused;
}
@keyframes ball-anim {
  0%   { left: 0; }
  50%  { left: calc(100% - 20px); }
  100% { left: 0; }
}
<div id="bar">
  <div id="ball"></div>
</div>

<script src="//code.jquery.com/jquery-3.1.0.js"></script>
Community
  • 1
  • 1
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
  • 2
    Simple and elegant! Thanks for your help. – thv20 Apr 19 '12 at 09:25
  • 2
    +1 for the jsFiddle demonstration. So helpful for a beginner/intermediate JQuery developer. Thank you. – nkha Apr 26 '12 at 17:25
  • 1
    would it make a difference performancewise to use translateX there? UPDATE -> seems like you can only animate basic properties. – artdias90 Jan 23 '15 at 12:45
  • 2
    @artdias90 edited my answer to reflect a CSS3 solution with `translate` – Roko C. Buljan Jan 23 '15 at 14:38
  • Thank you for your solid anwer/solution(s) Roko! For those of you who are interested, I further refined the CSS animation jsFiddle example to be javaScript free. http://jsfiddle.net/5rm4umnt – aschyiel Apr 28 '17 at 22:11
1

.animate() is a good way to do it. Example:

$(".scroll").hover(function(){
  $("#content").animate({
    marginLeft: "100px",
  }, 1500 );
});​

Working DEMO

Read the documentation to get the idea how to use it.

Alp
  • 29,274
  • 27
  • 120
  • 198
  • I'd nearly answered the same. What we've missed: The OP wants a continous animation (until the hover ends). AFAIS, animate() needs a "duration" argument. – Bergi Apr 18 '12 at 23:47