jQuery background animation - better performance

173 views Asked by At

I'm using backrground animation script like this:

$("body").bind('mousemove', function(e){

    $('#people').css({backgroundPosition: (e.pageX / 15 ) + 'px ' + (e.pageY / 15 - 100 ) + 'px' });
    $('#lady').css({backgroundPosition: (e.pageX / 10 ) + 'px ' + (e.pageY / 10 - 100 ) + 'px' });
    $('#city').css({backgroundPosition: (e.pageX / 30 ) + 'px ' + (e.pageY / 30 - 100 ) + 'px' });

});    

everything works fine, except the performance... it's going really laggy, especialy in opera, chrome and FF... in IE, everything works very smooth. Did anybody know, how to get better performance of this little script?

You can check the effect here: http://VisualStory.pl/test

3

There are 3 answers

0
torm On BEST ANSWER

I've change a code a little, to use 3D transform, and performance is much, much better, now the code look like this: var img3 = $('#lady'); var img2 = $('.img2'); var img1 = $('.img1'); var overlay = $('#particles');

overlay.mousemove(function(e){
    var amountMovedX = (e.pageX * -1 / 10);
    var amountMovedY = (e.pageY * -1 / 20);
    img3.css({
  '-webkit-transform' : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)',
  '-moz-transform'    : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)',
  '-ms-transform'     : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)',
  '-o-transform'      : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)',
  'transform'         : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)'
});
});

overlay.mousemove(function(e){
    var amountMovedX = (e.pageX * -1 / 15);
    var amountMovedY = (e.pageY * -1 / 25);
    img2.css({
  '-webkit-transform' : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)',
  '-moz-transform'    : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)',
  '-ms-transform'     : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)',
  '-o-transform'      : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)',
  'transform'         : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)'
    });

});


overlay.mousemove(function(e){
    var amountMovedX = (e.pageX * -1 / 20);
    var amountMovedY = (e.pageY * -1 / 30);
    img1.css({
  '-webkit-transform' : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)',
  '-moz-transform'    : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)',
  '-ms-transform'     : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)',
  '-o-transform'      : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)',
  'transform'         : 'translate3d(' + amountMovedX + 'px,' + amountMovedY + 'px, 0)'
    });



});
0
Gabe Noblesmith On

The mousemove function is simply doing too much work. All that math and string concatenation must be done EVERY time the mouse moves. This means every pixel. So if I move my mouse a moderate distance, say 300px that code has to execute 300 times. Which kills your performance.

You could try using a timer instead, only running the math say every 30ms instead of every time the mouse moves. Have you tried something entirely different, like an HTML5 canvas?

0
Tahir Ahmed On

On the website you mentioned, open the dev console, paste and execute this code below:

$('body').unbind('mousemove');
people=$('#people'),lady=$('#lady'),city=$('#city');
people.dest={x:0,y:0},lady.dest={x:0,y:0},city.dest={x:0,y:0},
xPeople=0,yPeople=0,xLady=0,yLady=0,xCity=0,yCity=0;
$('body').bind('mousemove',function(e){
  people.dest={x:e.pageX/15,y:e.pageY/15-100};
  lady.dest={x:e.pageX/10,y:e.pageY/10-100};
  city.dest={x:e.pageX/30,y:e.pageY/30-100};
});
//clearInterval(myIntervalID);
myIntervalID=setInterval(function(){
  people.css({backgroundPosition:parseInt(people.dest.x)+'px '+parseInt(people.dest.y)+'px'});
  lady.css({backgroundPosition:parseInt(lady.dest.x)+'px '+parseInt(lady.dest.y)+'px'});
  city.css({backgroundPosition:parseInt(city.dest.x)+'px '+parseInt(city.dest.y)+'px'});
},16);

Does the code above produce the desired result?

Below is my humble opinion about this approach:

  • Only record / store the destination values in the mousemove method.
  • Then use setInterval (or better requestAnimationFrame with a polyfill) to apply the recorded values to respective elements.

Hope it helps.