Holly
Holly

Reputation: 7752

Parallax scrolling jumpy in safari ios

I am working on a parallax feature and it's working fine on all browsers except for safari.

I've been following this article to see what I could be doing wrong and I think I've written my javascript wrong as I am binding directly to a scroll event.

This may be a dumb question but how should I begin my parallax scroll event without binding to a scroll event. I want the images to move at different speeds in different directicions as the user scrolls.

My JS

function onScroll() {

    window.requestAnimationFrame(parallax);
    function parallax(){
        var prlx_effect_1= +(window.pageYOffset *.55).toFixed(2); // .55 for slow | .7 good for fast
        var prlx_str_1 = "translate3d(0, "+prlx_effect_1+"px, 0)";
        jQ('.prlx-1').css({
            "transform":prlx_str_1,
            "-ms-transform":prlx_str_1,
            "-webkit-transform":prlx_str_1
        });

        var prlx_effect_2= -(window.pageYOffset *.25 ).toFixed(2); // .2 for slow | .4 good for fast
        var prlx_str_2 = "translate3d(0, "+prlx_effect_2+"px, 0)";
        jQ('.prlx-2').css({
            "transform":prlx_str_2,
            "-ms-transform":prlx_str_2,
            "-webkit-transform":prlx_str_2
        });
        window.requestAnimationFrame(parallax);
    }
}

window.addEventListener("scroll", onScroll, false); 

Any suggestions? Or could something else be causing the parallax to be jumpy on safari only?

Upvotes: 1

Views: 3693

Answers (1)

cuth
cuth

Reputation: 534

First, Add this debounce function from Underscore

// debounce is taken from _underscore.js
function debounce(func, wait, immediate) {
    var timeout, args, context, timestamp, result;
    return function() {
        context = this;
        args = arguments;
        timestamp = new Date();
        var later = function() {
            var last = (new Date()) - timestamp;
            if (last < wait) {
                timeout = setTimeout(later, wait - last);
            } else {
                timeout = null;
                if (!immediate) result = func.apply(context, args);
            }
        };
        var callNow = immediate && !timeout;
        if (!timeout) {
            timeout = setTimeout(later, wait);
        }
        if (callNow) result = func.apply(context, args);
        return result;
    };
}

Start the requestAnimationFrame loop when the user begins scrolling and kill it 100 milliseconds after the last scroll event using a flag.

var requesting = false;

var killRequesting = debounce(function () {
    requesting = false;
}, 100);

function onScroll() {
    if (!requesting) {
        requesting = true;
        requestAnimationFrame(parallax);
    }
    killRequesting();
}

Now in your parallax function check the flag before calling itself again.

function parallax() {
    // your parallax code
    if (requesting) {
        requestAnimationFrame(parallax);
    }
}

Second, you should always cache your jQuery selectors.

var $prlx1 = jQ('.prlx-1');
var $prlx2 = jQ('.prlx-2');
function parallax(){
    var prlx_effect_1= +(window.pageYOffset *.55).toFixed(2); // .55 for slow | .7 good for fast
    var prlx_str_1 = "translate3d(0, "+prlx_effect_1+"px, 0)";
    $prlx1.css({
        "transform":prlx_str_1,
        "-ms-transform":prlx_str_1,
        "-webkit-transform":prlx_str_1
    });

    var prlx_effect_2= -(window.pageYOffset *.25 ).toFixed(2); // .2 for slow | .4 good for fast
    var prlx_str_2 = "translate3d(0, "+prlx_effect_2+"px, 0)";
    $prlx2.css({
        "transform":prlx_str_2,
        "-ms-transform":prlx_str_2,
        "-webkit-transform":prlx_str_2
    });
    if (requesting) {
        window.requestAnimationFrame(parallax);
    }
}

Upvotes: 2

Related Questions