Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I improve performance on my parallax scroll script?

I'm using Javascript & jQuery to build a parallax scroll script that manipulates an image in a figure element using transform:translate3d, and based on the reading I've done (Paul Irish's blog, etc), I've been informed the best solution for this task is to use requestAnimationFrame for performance reasons.

Although I understand how to write Javascript, I'm always finding myself uncertain of how to write good Javascript. In particular, while the code below seems to function correctly and smoothly, I'd like to get a few issues resolved that I'm seeing in Chrome Dev Tools.

$(document).ready(function() {
    function parallaxWrapper() {
        // Get the viewport dimensions
        var viewportDims = determineViewport();         
        var parallaxImages = [];
        var lastKnownScrollTop;

        // Foreach figure containing a parallax 
        $('figure.parallax').each(function() {
            // Save information about each parallax image
            var parallaxImage = {};
            parallaxImage.container = $(this);
            parallaxImage.containerHeight = $(this).height();
            // The image contained within the figure element
            parallaxImage.image = $(this).children('img.lazy');
            parallaxImage.offsetY = parallaxImage.container.offset().top;

            parallaxImages.push(parallaxImage);
        });

        $(window).on('scroll', function() {
            lastKnownScrollTop = $(window).scrollTop();
        });

        function animateParallaxImages() {
            $.each(parallaxImages, function(index, parallaxImage) {
                var speed = 3;
                var delta = ((lastKnownScrollTop + ((viewportDims.height - parallaxImage.containerHeight) / 2)) - parallaxImage.offsetY) / speed;
                parallaxImage.image.css({ 
                    'transform': 'translate3d(0,'+ delta +'px,0)'
                });
            });     
            window.requestAnimationFrame(animateParallaxImages);
        }
        animateParallaxImages();
    }

    parallaxWrapper();
});

Firstly, when I head to the 'Timeline' tab in Chrome Dev Tools, and start recording, even with no actions on the page being performed, the "actions recorded" overlay count continues to climb, at a rate of about ~40 per second.

Secondly, why is an "animation frame fired" executing every ~16ms, even when I am not scrolling or interacting with the page, as shown by the image below?

Thirdly, why is the Used JS Heap increasing in size without me interacting with the page? As shown in the image below. I have eliminated all other scripts that could be causing this.

Chrome dev tools.

Can anyone help me with some pointers to fix the above issues, and give me suggestions on how I should improve my code?

like image 238
marked-down Avatar asked Dec 29 '14 08:12

marked-down


1 Answers

(1 & 2 -- same answer) The pattern you are using creates a repeating animating loop which attempts to fire at the same rate as the browser refreshes. That's usually 60 time per second so the activity you're seeing is the loop executing approximately every 1000/60=16ms. If there's no work to do, it still fires every 16ms.

(3) The browser consumes memory as needed for your animations but the browser does not reclaim that memory immediately. Instead it occasionally reclaims any orphaned memory in a process called garbage collection. So your memory consumption should go up for a while and then drop in a big chunk. If it doesn't behave that way, then you have a memory leak.

like image 53
markE Avatar answered Oct 10 '22 14:10

markE