Wednesday, 22 September 2021

Parallax-Animation with transform3d, throttle, requestAnimationFrame, will-change still laggy on Mobile and Desktop, Chrome and Safari

I am currently try to develop a small lightweight vanilla-js parallax-library which gives the possibility to parallax elements (images, videos, sliders, ...) horizontally and vertically in both directions without any background-position things.

It works very well so far and does a great job expecting one important detail: Sometimes it's still laggy. I've tested it on Mac OS and iPhone, in Safari and Chromebrowser. For all the same.

I have tried to use the common practices like throttling, requestAnimationFrame and CSS's will-change but without success.

I am not sure, if it's possible to see the lags here in this video.

But I made an example where you could test it: https://codepen.io/flexplosion/pen/RwgQXxo?editors=1111

Someone has an idea, how I can improve the scrolling-performance for the parallax?

var parallaxes = document.getElementsByClassName('parallax');

const windowInnerHeight = window.innerHeight;

function throttle (callback, limit) {
    var wait = false;                 // Initially, we're not waiting
    return function () {              // We return a throttled function
        if (!wait) {                  // If we're not waiting
            callback.call();          // Execute users function
            wait = true;              // Prevent future invocations
            setTimeout(function () {  // After a period of time
                wait = false;         // And allow future invocations
            }, limit);
        }
    }
 }


Array.from(parallaxes).forEach((parallax) => {
    const movement = parseFloat(parallax.dataset.movement),
        direction = parallax.dataset.direction,
        element = parallax.children[0];
    
    if( direction == 'horizontal' ) {
        // Prepare for orzintal
        element.style.height = '100%';
        element.style.width = (100 + movement) + "%";

    } else {
        // Otherwise prepare for vertical
        element.style.height = (100 + movement) + "%";
        element.style.width = '100%';
    }
});

const handleScroll = () => {
    var parallaxes = document.getElementsByClassName('parallax');
    Array.from(parallaxes).forEach((parallax) => {
        const movement = parseFloat(parallax.dataset.movement),
            direction = parallax.dataset.direction,
            reverse = parallax.dataset.reverse === 'true',
            element = parallax.children[0];

        var containerReact = parallax.getBoundingClientRect();
        var scrolledInContainer = 0 - (containerReact.top -  windowInnerHeight);
        var scrollArea = windowInnerHeight + containerReact.height;
        var progress = scrolledInContainer / scrollArea;
        var scrolledInContainer = window.pageYOffset - (containerReact.top - windowInnerHeight);
        
        if(progress > 0 && progress < 1) {
            
            requestAnimationFrame(() => {
                var position = reverse
                    ? movement * progress
                    : movement - movement * progress;
                
                element.style[ direction == 'horizontal' ? 'left' : 'top'] = "-" + position + "%";
            });
        }
    });
}

// Initialize
handleScroll();

// Hook into event
window.addEventListener('scroll', throttle(handleScroll, 10) );

UPDATE 1:

I tried to switch the script to use translate3d instead of top/left properties. The animation on Desktop (Chrome) is now ultra-smooth. Exactly how it should be. In Safari and all mobile Browsers it didn't really help...

https://codepen.io/flexplosion/pen/BaZrKYv

In Safari (same on mobile Chrome and Safari): https://jmp.sh/n4JG8J5 In Chrome: https://jmp.sh/EMM7y1Z



from Parallax-Animation with transform3d, throttle, requestAnimationFrame, will-change still laggy on Mobile and Desktop, Chrome and Safari

No comments:

Post a Comment