Page Scroll Effects - VelocityJS - (Page Anchors with Data-hijacking enabled)

538 views Asked by At

I'm stuck with my page scroll effects.

This is what I've got so far - https://codepen.io/DCRSLG/pen/jzYJeY

$(document).ready(function($) {
//variables
var hijacking = $('body').data('hijacking'),
    animationType = $('body').data('animation'),
    delta = 0,
    scrollThreshold = 5,
    actual = 1,
    animating = false;
//DOM elements
var sectionsAvailable = $('.cd-section'),
    verticalNav = $('.cd-vertical-nav'),
    prevArrow = verticalNav.find('a.cd-prev'),
    nextArrow = verticalNav.find('a.cd-next');
//check the media query and bind corresponding events
var MQ = deviceType(),
    bindToggle = false;

bindEvents(MQ, true);

$(window).on('resize', function() {
    MQ = deviceType();
    bindEvents(MQ, bindToggle);
    if (MQ == 'mobile') bindToggle = true;
    if (MQ == 'desktop') bindToggle = false;
});

function bindEvents(MQ, bool) {

    if (MQ == 'desktop' && bool) {
        //bind the animation to the window scroll event, arrows click and keyboard
        if (hijacking == 'on') {
            initHijacking();
            $(window).on('DOMMouseScroll mousewheel', scrollHijacking);
        } else {
            scrollAnimation();
            $(window).on('scroll', scrollAnimation);
        }
        prevArrow.on('click', prevSection);
        nextArrow.on('click', nextSection);
  $('a[href*="#"]').on('click', function(e) {
    e.preventDefault();
    e.stopPropagation();
      var target = $(this).attr('href');
      $(target).velocity('scroll', {
        duration: 3000,
        offset: 0,
        easing: 'ease-in-out',
        mobileHA: false
      });
  });

        $(document).on('keydown', function(event) {
            if (event.which == '40' && !nextArrow.hasClass('inactive')) {
                event.preventDefault();
                nextSection();
            } else if (event.which == '38' && (!prevArrow.hasClass('inactive') || (prevArrow.hasClass('inactive') && $(window).scrollTop() != sectionsAvailable.eq(0).offset().top))) {
                event.preventDefault();
                prevSection();
            }
        });
        //set navigation arrows visibility
        checkNavigation();
    } else if (MQ == 'mobile') {
        //reset and unbind
        resetSectionStyle();
        $(window).off('DOMMouseScroll mousewheel', scrollHijacking);
        $(window).off('scroll', scrollAnimation);
        prevArrow.off('click', prevSection);
        nextArrow.off('click', nextSection);
        $(document).off('keydown');
    }
}

function scrollAnimation() {
    //normal scroll - use requestAnimationFrame (if defined) to optimize performance
    (!window.requestAnimationFrame) ? animateSection(): window.requestAnimationFrame(animateSection);
}

function animateSection() {
    var scrollTop = $(window).scrollTop(),
        windowHeight = $(window).height(),
        windowWidth = $(window).width();

    sectionsAvailable.each(function() {
        var actualBlock = $(this),
            offset = scrollTop - actualBlock.offset().top;

        //according to animation type and window scroll, define animation parameters
        var animationValues = setSectionAnimation(offset, windowHeight, animationType);

        transformSection(actualBlock.children('div'), animationValues[0], animationValues[1], animationValues[2], animationValues[3], animationValues[4]);
        (offset >= 0 && offset < windowHeight) ? actualBlock.addClass('visible'): actualBlock.removeClass('visible');
    });

    checkNavigation();
}

function transformSection(element, translateY, scaleValue, rotateXValue, opacityValue, boxShadow) {
    //transform sections - normal scroll
    element.velocity({
        translateY: translateY + 'vh',
        scale: scaleValue,
        rotateX: rotateXValue,
        opacity: opacityValue,
        boxShadowBlur: boxShadow + 'px',
        translateZ: 0,
    }, 0);
}

function initHijacking() {
    // initialize section style - scrollhijacking
    var visibleSection = sectionsAvailable.filter('.visible'),
        topSection = visibleSection.prevAll('.cd-section'),
        bottomSection = visibleSection.nextAll('.cd-section'),
        animationParams = selectAnimation(animationType, false),
        animationVisible = animationParams[0],
        animationTop = animationParams[1],
        animationBottom = animationParams[2];

    visibleSection.children('div').velocity(animationVisible, 1, function() {
        visibleSection.css('opacity', 1);
        topSection.css('opacity', 1);
        bottomSection.css('opacity', 1);
    });
    topSection.children('div').velocity(animationTop, 0);
    bottomSection.children('div').velocity(animationBottom, 0);
}

function scrollHijacking(event) {
    // on mouse scroll - check if animate section
    if (event.originalEvent.detail < 0 || event.originalEvent.wheelDelta > 0) {
        delta--;
        (Math.abs(delta) >= scrollThreshold) && prevSection();
    } else {
        delta++;
        (delta >= scrollThreshold) && nextSection();
    }
    return false;
}

function prevSection(event) {
    //go to previous section
    typeof event !== 'undefined' && event.preventDefault();

    var visibleSection = sectionsAvailable.filter('.visible'),
        middleScroll = (hijacking == 'off' && $(window).scrollTop() != visibleSection.offset().top) ? true : false;
    visibleSection = middleScroll ? visibleSection.next('.cd-section') : visibleSection;

    var animationParams = selectAnimation(animationType, middleScroll, 'prev');
    unbindScroll(visibleSection.prev('.cd-section'), animationParams[3]);

    if (!animating && !visibleSection.is(":first-child")) {
        animating = true;
        visibleSection.removeClass('visible').children('div').velocity(animationParams[2], animationParams[3], animationParams[4])
            .end().prev('.cd-section').addClass('visible').children('div').velocity(animationParams[0], animationParams[3], animationParams[4], function() {
                animating = false;
                if (hijacking == 'off') $(window).on('scroll', scrollAnimation);
            });

        actual = actual - 1;
    }

    resetScroll();
}

function nextSection(event) {
    //go to next section
    typeof event !== 'undefined' && event.preventDefault();

    var visibleSection = sectionsAvailable.filter('.visible'),
        middleScroll = (hijacking == 'off' && $(window).scrollTop() != visibleSection.offset().top) ? true : false;

    var animationParams = selectAnimation(animationType, middleScroll, 'next');
    unbindScroll(visibleSection.next('.cd-section'), animationParams[3]);

    if (!animating && !visibleSection.is(":last-of-type")) {
        animating = true;
        visibleSection.removeClass('visible').children('div').velocity(animationParams[1], animationParams[3], animationParams[4])
            .end().next('.cd-section').addClass('visible').children('div').velocity(animationParams[0], animationParams[3], animationParams[4], function() {
                animating = false;
                if (hijacking == 'off') $(window).on('scroll', scrollAnimation);
            });

        actual = actual + 1;
    }
    resetScroll();
}

function unbindScroll(section, time) {
    //if clicking on navigation - unbind scroll and animate using custom velocity animation
    if (hijacking == 'off') {
        $(window).off('scroll', scrollAnimation);
        (animationType == 'catch') ? $('body, html').scrollTop(section.offset().top): section.velocity("scroll", {
            duration: time
        });
    }
}

function resetScroll() {
    delta = 0;
    checkNavigation();
}

function checkNavigation() {
    //update navigation arrows visibility
    (sectionsAvailable.filter('.visible').is(':first-of-type')) ? prevArrow.addClass('inactive'): prevArrow.removeClass('inactive');
    (sectionsAvailable.filter('.visible').is(':last-of-type')) ? nextArrow.addClass('inactive'): nextArrow.removeClass('inactive');
}

function resetSectionStyle() {
    //on mobile - remove style applied with jQuery
    sectionsAvailable.children('div').each(function() {
        $(this).attr('style', '');
    });
}

function deviceType() {
    //detect if desktop/mobile
    return window.getComputedStyle(document.querySelector('body'), '::before').getPropertyValue('content').replace(/"/g, "").replace(/'/g, "");
}

function selectAnimation(animationName, middleScroll, direction) {
    // select section animation - scrollhijacking
    var animationVisible = 'translateNone',
        animationTop = 'translateUp',
        animationBottom = 'translateDown',
        easing = 'ease',
        animDuration = 800;

    switch (animationName) {
        case 'gallery':
            animDuration = 1500;
            if (middleScroll) {
                animationTop = 'scaleDown.moveUp.scroll';
                animationVisible = 'scaleUp.moveUp.scroll';
                animationBottom = 'scaleDown.moveDown.scroll';
            } else {
                animationVisible = (direction == 'next') ? 'scaleUp.moveUp' : 'scaleUp.moveDown';
                animationTop = 'scaleDown.moveUp';
                animationBottom = 'scaleDown.moveDown';
            }
            break;
    }

    return [animationVisible, animationTop, animationBottom, animDuration, easing];
}

function setSectionAnimation(sectionOffset, windowHeight, animationName) {
    // select section animation - normal scroll
    var scale = 1,
        translateY = 100,
        rotateX = '0deg',
        opacity = 1,
        boxShadowBlur = 0;

    if (sectionOffset >= -windowHeight && sectionOffset <= 0) {
        // section entering the viewport
        translateY = (-sectionOffset) * 100 / windowHeight;

        switch (animationName) {
            case 'gallery':
                if (sectionOffset >= -windowHeight && sectionOffset < -0.9 * windowHeight) {
                    scale = -sectionOffset / windowHeight;
                    translateY = (-sectionOffset) * 100 / windowHeight;
                    boxShadowBlur = 400 * (1 + sectionOffset / windowHeight);
                } else if (sectionOffset >= -0.9 * windowHeight && sectionOffset < -0.1 * windowHeight) {
                    scale = 0.9;
                    translateY = -(9 / 8) * (sectionOffset + 0.1 * windowHeight) * 100 / windowHeight;
                    boxShadowBlur = 40;
                } else {
                    scale = 1 + sectionOffset / windowHeight;
                    translateY = 0;
                    boxShadowBlur = -400 * sectionOffset / windowHeight;
                }
                break;
        }
    } else if (sectionOffset > 0 && sectionOffset <= windowHeight) {
        //section leaving the viewport - still has the '.visible' class
        translateY = (-sectionOffset) * 100 / windowHeight;

        switch (animationName) {
            case 'gallery':
                if (sectionOffset >= 0 && sectionOffset < 0.1 * windowHeight) {
                    scale = (windowHeight - sectionOffset) / windowHeight;
                    translateY = -(sectionOffset / windowHeight) * 100;
                    boxShadowBlur = 400 * sectionOffset / windowHeight;
                } else if (sectionOffset >= 0.1 * windowHeight && sectionOffset < 0.9 * windowHeight) {
                    scale = 0.9;
                    translateY = -(9 / 8) * (sectionOffset - 0.1 * windowHeight / 9) * 100 / windowHeight;
                    boxShadowBlur = 40;
                } else {
                    scale = sectionOffset / windowHeight;
                    translateY = -100;
                    boxShadowBlur = 400 * (1 - sectionOffset / windowHeight);
                }
                break;
        }
    } else if (sectionOffset < -windowHeight) {
        translateY = 100;

        switch (animationName) {
            case 'gallery':
                scale = 1;
                break;
        }
    } else {
        //section not visible anymore
        translateY = -100;
        switch (animationName) {
            case 'gallery':
                scale = 1;
                break;
        }
    }

    return [translateY, scale, rotateX, opacity, boxShadowBlur];
}
});

/* Custom effects registration - feature available in the Velocity UI pack */

//gallery
$.Velocity
    .RegisterEffect("scaleDown.moveUp", {
        defaultDuration: 1,
        calls: [
            [{
                translateY: '-10%',
                scale: '0.9',
                boxShadowBlur: '40px'
            }, 0.20],
            [{
                translateY: '-100%'
            }, 0.60],
            [{
                translateY: '-100%',
                scale: '1',
                boxShadowBlur: '0'
            }, 0.20]
        ]
    });
$.Velocity
    .RegisterEffect("scaleDown.moveUp.scroll", {
        defaultDuration: 1,
        calls: [
            [{
                translateY: '-100%',
                scale: '0.9',
                boxShadowBlur: '40px'
            }, 0.60],
            [{
                translateY: '-100%',
                scale: '1',
                boxShadowBlur: '0'
            }, 0.40]
        ]
    });
$.Velocity
    .RegisterEffect("scaleUp.moveUp", {
        defaultDuration: 1,
        calls: [
            [{
                translateY: '90%',
                scale: '0.9',
                boxShadowBlur: '40px'
            }, 0.20],
            [{
                translateY: '0%'
            }, 0.60],
            [{
                translateY: '0%',
                scale: '1',
                boxShadowBlur: '0'
            }, 0.20]
        ]
    });
$.Velocity
    .RegisterEffect("scaleUp.moveUp.scroll", {
        defaultDuration: 1,
        calls: [
            [{
                translateY: '0%',
                scale: '0.9',
                boxShadowBlur: '40px'
            }, 0.60],
            [{
                translateY: '0%',
                scale: '1',
                boxShadowBlur: '0'
            }, 0.40]
        ]
    });
$.Velocity
    .RegisterEffect("scaleDown.moveDown", {
        defaultDuration: 1,
        calls: [
            [{
                translateY: '10%',
                scale: '0.9',
                boxShadowBlur: '40px'
            }, 0.20],
            [{
                translateY: '100%'
            }, 0.60],
            [{
                translateY: '100%',
                scale: '1',
                boxShadowBlur: '0'
            }, 0.20]
        ]
    });
$.Velocity
    .RegisterEffect("scaleDown.moveDown.scroll", {
        defaultDuration: 1,
        calls: [
            [{
                translateY: '100%',
                scale: '0.9',
                boxShadowBlur: '40px'
            }, 0.60],
            [{
                translateY: '100%',
                scale: '1',
                boxShadowBlur: '0'
            }, 0.40]
        ]
    });
$.Velocity
    .RegisterEffect("scaleUp.moveDown", {
        defaultDuration: 1,
        calls: [
            [{
                translateY: '-90%',
                scale: '0.9',
                boxShadowBlur: '40px'
            }, 0.20],
            [{
                translateY: '0%'
            }, 0.60],
            [{
                translateY: '0%',
                scale: '1',
                boxShadowBlur: '0'
            }, 0.20]
        ]
    });

I'm trying to get it so the Dots on the right hand side can be a reference to scroll down to each section like this:

https://codyhouse.co/demo/vertical-fixed-navigation/index.html

  $('a[href*="#"]').on('click', function(e) {
e.preventDefault();
e.stopPropagation();
  var target = $(this).attr('href');
  $(target).velocity('scroll', {
    duration: 3000,
    offset: 0,
    easing: 'ease-in-out',
    mobileHA: false
  });
});

I can get it to work using the above code providing I disable data-hijacking on the scroll, does anyone know of a way to get this to work while keep data-hijacking enabled?

0

There are 0 answers