简体   繁体   中英

Vertical scrolling parallax background effect

Background

I have been asked to write a script that will create a vertical scrolling parallax background effect for a project. My initial attempt looks a little 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 does give the required effect, but the bind on the scroll event is a real performance drain.

Question

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

You may 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);

So the browser will not scroll the background if there are multiple scroll events is sequence. I wrote func outside the event handler to avoid the creation of a new closure in every event.

You should make the actual "scroll" event handler start a 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. This way, you're only doing the DOM manipulation at most 10 times a second.

One thing you could do is instead of:

            $(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 the window jQuery 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"
                });
            }
        });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM