The effect of vertical scrolling parallax

Background

I was asked to write a script that would create a vertical scrolling parallax background effect for the project. My initial attempt looks something like this:

(function($){ $.fn.parallax = function(options){ var $$ = $(this); offset = $$.offset(); var defaults = { "start": 0, "stop": offset.top + $$.height(), "coeff": 0.95 }; var opts = $.extend(defaults, options); return this.each(function(){ $(window).bind('scroll', function() { windowTop = $(window).scrollTop(); if((windowTop >= opts.start) && (windowTop <= opts.stop)) { newCoord = windowTop * opts.coeff; $$.css({ "background-position": "0 "+ newCoord + "px" }); } }); }); }; })(jQuery); // call the plugin $('.lines1').parallax({ "coeff":0.65 }); $('.lines1 .lines2').parallax({ "coeff":1.15 }); 

This code gives the desired effect, but binding to a scroll event is a real performance leak.

Question

Part 1. How can I change my plugin to be more efficient? Part 2. Are there resources (books, links, tutorials) that I can read to learn more?

0
source share
3 answers

You can try something like:

 (function($){ $.fn.parallax = function(options){ var $$ = $(this); offset = $$.offset(); var defaults = { "start": 0, "stop": offset.top + $$.height(), "coeff": 0.95 }; var timer = 0; var opts = $.extend(defaults, options); var func = function(){ timer = 0; var windowTop = $(window).scrollTop(); if((windowTop >= opts.start) && (windowTop <= opts.stop)) { newCoord = windowTop * opts.coeff; $$.css({ "background-position": "0 "+ newCoord + "px" }); } }; return this.each(function(){ $(window).bind('scroll', function() { window.clearTimeout(timer); timer = window.setTimeout(func, 1); }); }); }; })(jQuery); 

Thus, the browser will not scroll the background, if there are several scroll events, this is the sequence. I wrote func outside the event handler to avoid creating a new closure in each event.

+2
source

You must force the actual "scroll" event handler to start the timer:

  var opts = $.extend(defaults, options); var newCoord = null, prevCoord = null; setInterval(function() { if (newCoord !== null && newCoord !== prevCoord) { $$.css({ "background-position": "0 "+ newCoord + "px" }); prevCoord = newCoord; } }, 100); return this.each(function(){ $(window).bind('scroll', function() { windowTop = $(window).scrollTop(); if((windowTop >= opts.start) && (windowTop <= opts.stop)) { newCoord = windowTop * opts.coeff; } else prevCoord = newCoord = null; }); }); 

Or something like that. Thus, you perform DOM manipulations no more than 10 times per second.

+1
source

The only thing you could do is not:

  $(window).bind('scroll', function() { windowTop = $(window).scrollTop(); if((windowTop >= opts.start) && (windowTop <= opts.stop)) { newCoord = windowTop * opts.coeff; $$.css({ "background-position": "0 "+ newCoord + "px" }); } }); 

You can create a jQuery window object outside of the scroll event.

  $window = $(window); //create jQuery object $window.bind('scroll', function() { windowTop = $window.scrollTop(); if((windowTop >= opts.start) && (windowTop <= opts.stop)) { newCoord = windowTop * opts.coeff; $$.css({ "background-position": "0 "+ newCoord + "px" }); } }); 
0
source

Source: https://habr.com/ru/post/1483883/


All Articles