When I enter the main page (index.html) and navigate to the work page everything works as expected. But once I refresh the page in the workpage and not the initial page everything stops working -- what could be the reason for this?
I've tried refreshing animations in the barbajs code and it seems that it doesn't work even with the usage of Barba views to reinitialize the animations explicitly.
YOUTUBE VIDEO: https://www.youtube.com/watch?v=FbkBvcjlCYI&t=33s
// Main Scripts
function initScripts() {
initNavAnimations();
initMagneticButtons();
initButtonsAnimations();
initHomeAnimations();
//initWorkPageAnimations() --> it used to be here but I'm now calling it specifically on the barba view to see if something works.
}
// NOTE: data.next = current container
barba.init({
sync: true,
timeout: 7000,
debug: true, // !IMPORTANT
views: [{ // THIS IS WHERE I'M CALLING MANUALLY BUT NOTHING STILL WORKS
namespace: 'work-page',
afterEnter() {
initWorkAnimations();
ScrollTrigger.refresh();
console.log('WORRRRRRK PAFGE ENTER');
},
}],
transitions: [{
name: 'default',
async once(data) {
// Once page loads
initSmoothScroll(data.next.container);
initScripts();
},
async leave(data) {
pageTransitionIn(data, this)
await delay(1200)
data.current.container.remove();
},
async enter(data) {
pageTransitionOut(data, this);
},
async beforeEnter(data) {
ScrollTrigger.getAll().forEach((x) => x.kill());
console.log('destroying everything');
locoScroll.destroy(); // Optional!
initSmoothScroll(data.next.container);
initScripts();
ScrollTrigger.refresh(); // IMPORTANT!
}
},
{ // Optional
name: 'to-home',
from: {
},
to: {
namespace: ['first-page']
},
once(data) {
// do something once on the initial page load
initSmoothScroll(data.next.container);
initScripts();
},
}]
})
The full code is here:
const intro = document.querySelector('.loading__container');
const word = document.querySelector('.word');
const content = document.querySelector('.content');
let locoScroll;
// On Load Animation
window.addEventListener('load', () => {
word.classList.add('loading--active');
gsap.set("html", {
cursor: "wait"
});
setTimeout(() => {
gsap.set("html", {
cursor: "auto"
}, "=-0.6");
intro.classList.add('loading--inactive');
word.classList.remove('loading--active');
}, 1500)
// Remove right after load
setTimeout(() => {
intro.remove();
}, 2000)
});
function initSmoothScroll(container) {
// Scrolling Animation
locoScroll = new LocomotiveScroll({
el: container.querySelector('[data-scroll-container]'),
smooth: true,
multiplier: 1,
smoothMobile: true,
});
// each time Locomotive Scroll updates, tell ScrollTrigger to update too (sync positioning)
locoScroll.on("scroll", ScrollTrigger.update);
// tell ScrollTrigger to use these proxy methods for the ".smooth-scroll" element since Locomotive Scroll is hijacking things
ScrollTrigger.scrollerProxy("[data-scroll-container]", {
scrollTop(value) {
return arguments.length ? locoScroll.scrollTo(value, { duration: 0, disableLerp: true }) : locoScroll.scroll.instance.scroll.y;
}, // we don't have to define a scrollLeft because we're only scrolling vertically.
getBoundingClientRect() {
return { top: 0, left: 0, width: window.innerWidth, height: window.innerHeight };
},
// LocomotiveScroll handles things completely differently on mobile devices - it doesn't even transform the container at all! So to get the correct behavior and avoid jitters, we should pin things with position: fixed on mobile. We sense it by checking to see if there's a transform applied to the container (the LocomotiveScroll-controlled element).
pinType: container.querySelector("[data-scroll-container]").style.transform ? "transform" : "fixed"
});
// each time the window updates, we should refresh ScrollTrigger and then update LocomotiveScroll.
ScrollTrigger.addEventListener("refresh", () => locoScroll.update());
ScrollTrigger.defaults({ scroller: "[data-scroll-container]" });
// each time the window updates, we should refresh ScrollTrigger and then update LocomotiveScroll.
ScrollTrigger.addEventListener('refresh', () => locoScroll.update());
// after everything is set up, refresh() ScrollTrigger and update LocomotiveScroll because padding may have been added for pinning, etc.
ScrollTrigger.refresh();
}
function initHomeAnimations() {
if (document.body.id === 'first-page') {
//Page 2
const tlH = gsap.timeline({
scrollTrigger: {
trigger: '.background',
// markers: { startColor: 'blue', endColor: 'blue' },
scrub: true,
start: '-40%',
end: '40%',
},
});
tlH.fromTo('.highlight', { color: 'rgba(255, 255, 255, 0.4)' }, { color: 'rgba(255, 255, 255, 1)', stagger: 1 });
const tlHRemove = gsap.timeline({
scrollTrigger: {
trigger: '.background',
// markers: { startColor: 'pink', endColor: 'pink' },
scrub: true,
start: '-20%',
end: '60%',
},
});
tlHRemove.to('.highlight', { color: 'rgba(255, 255, 255, 0.4)', stagger: 1 });
// Work Experience Fade Text
const tlFade = gsap.timeline({
scrollTrigger: {
trigger: '.work',
toggleActions: 'play none none reset',
scrub: true,
start: '60%',
end: '120%',
// markers: true,
},
});
/**
* Allow pinning animation only for Desktop/Ipad users
* Fade In for Desktop Accordingly
*/
ScrollTrigger.matchMedia({
"(min-width: 820px)": function () {
const pinSecond = gsap.timeline({
scrollTrigger: {
trigger: '.background',
pin: true,
start: '0%',
end: '100%',
}
});
tlFade.fromTo('.work__description', { opacity: 0, y: 50 }, { opacity: 1, y: 0, duration: 1.2 });
tlFade.fromTo('.work-btn', { opacity: 0, y: 50 }, { opacity: 1, y: 0, duration: 1.2 });
},
// Reset fade for mobile
"(max-width: 540px)": function () {
gsap.set('.work__description', { opacity: 1, y: 0, duration: 1 });
},
})
}
}
function initButtonsAnimations() {
/**
* BtnFill
* If button is hover do the animation else reset
*/
const btnClick = document.querySelectorAll('.btn-click');
btnClick.forEach(e => {
const btnFill = e.querySelector('.btn-fill');
gsap.to(btnFill, { y: '-76%', ease: Power2.easeInOut });
e.addEventListener('mouseenter', function () {
gsap.to(btnFill, .5, { startAt: { y: '76%' }, y: '0%', ease: Power2.easeInOut });
});
e.addEventListener('mouseleave', function () {
gsap.to(btnFill, .5, { y: '-76%', ease: Power2.easeInOut });
})
})
}
function initNavAnimations() {
// Nav
const tlIntro = gsap.timeline({
scrollTrigger: {
trigger: '.intro',
start: '20%',
toggleActions: 'play none none reverse',
pin: true,
pinSpacing: false,
// markers: true
},
});
tlIntro.fromTo('nav', { opacity: 1 }, { opacity: 0, duration: .60 });
const tlPopUpNav = gsap.timeline({
scrollTrigger: {
trigger: '.btn-hamburger',
start: '0%',
toggleActions: 'play none none reverse',
// markers: true
},
});
tlPopUpNav.fromTo('.btn-hamburger', { scale: '0' }, { scale: '1' });
/**
* Animated nav lines when clicked
* Initially hide the nav, if clicked move it xPercent: 1 (active) and reduce with to standard look
* Make sure to move it right -90% to hide it.
*
* Otherwise, put it back to normal to normal width and hiding the rounded div as far possible
*/
const burger = document.querySelector('.btn-hamburger');
const fixedNav = document.querySelector('.fixed-nav');
const clickables = document.querySelectorAll('.clickable');
burger.addEventListener('click', navToggle);
gsap.set('.fixed-nav', { xPercent: 140 }); // hide
function navToggle(e) {
if (!fixedNav.classList.contains('nav-active')) {
fixedNav.classList.add('nav-active');
gsap.to('.header__nav__line1', 0.5, { rotate: '45', y: 0 });
gsap.to('.header__nav__line2', 0.5, { rotate: '-45', y: -5 });
gsap.to('.fixed-nav', { xPercent: -0 });
gsap.to('.rounded-div', { width: '3vw', right: '-90%' }, '<'); // most left
} else {
removeNav();
}
// remove if clicked on a nav btn
clickables.forEach((clickable) => {
clickable.addEventListener('click', removeNav);
})
function removeNav() {
fixedNav.classList.remove('nav-active');
gsap.to('.header__nav__line1', 0.5, { rotate: '0', y: 0 });
gsap.to('.header__nav__line2', 0.5, { rotate: '0', y: 0 });
gsap.to('.fixed-nav', { xPercent: 150 }); // hide
// Fix rounded div for mobile
if (window.innerWidth > 540)
gsap.to('.rounded-div', { width: '775%', right: '-390%', xPercent: 10 }, '<');
else
gsap.to('.rounded-div', { width: '775%', right: '-500%', xPercent: 10 }, '<');
}
}
}
function initMagneticButtons() {
const magnets = document.querySelectorAll('.magnetic');
// START : If screen is bigger as 540 px do magnetic
if (window.innerWidth > 540) {
// Reset the mouse if hover off otherwise play the animation
magnets.forEach((magnet) => {
magnet.addEventListener('mousemove', moveMagnet);
magnet.addEventListener('mouseleave', function (event) {
gsap.to(event.currentTarget, 1.5, {
x: 0,
y: 0,
ease: Elastic.easeOut
});
gsap.to(".btn-text", 1.5, {
x: 0,
y: 0,
ease: Elastic.easeOut
});
});
});
// Mouse move
function moveMagnet(event) {
var magnetButton = event.currentTarget;
var bounding = magnetButton.getBoundingClientRect();
const magnetsStrength = 80;
const magnetStrengthText = 60;
gsap.to(magnetButton, {
x: (((event.clientX - bounding.left) / magnetButton.offsetWidth) - 0.5) * magnetsStrength,
y: (((event.clientY - bounding.top) / magnetButton.offsetHeight) - 0.5) * magnetsStrength,
rotate: "0.001deg",
ease: Power4.easeOut
});
}
}
}
function initWorkAnimations() {
if (document.body.id === 'first-page') {
const container = document.querySelector('.scrollx');
const sections = gsap.utils.toArray('.scrollx section');
const texts = gsap.utils.toArray('anim');
const mask = document.querySelector('.mask');
// Preference
const nav = document.querySelector('.nav');
nav.classList.add('absolute-nav');
let scrollTween = gsap.to(sections, {
xPercent: -100 * (sections.length - 1),
ease: 'none',
scrollTrigger: {
trigger: '.scrollx',
pin: true,
scrub: 1,
end: '+=3000',
markers: true,
}
})
gsap.to(mask, {
width: '100%',
scrollTrigger: {
trigger: '.wrapper',
start: 'top left',
scrub: 1
}
});
}
}
// Main Scripts
function initScripts() {
initNavAnimations();
initMagneticButtons();
initButtonsAnimations();
initHomeAnimations();
}
// NOTE: data.next = current container
barba.init({
sync: true,
timeout: 7000,
debug: true, // !IMPORTANT
views: [{
namespace: 'work-page',
afterEnter() {
initWorkAnimations();
ScrollTrigger.refresh();
console.log('WORRRRRRK PAFGE ENTER');
},
}],
transitions: [{
name: 'default',
async once(data) {
// Once page loads
initSmoothScroll(data.next.container);
initScripts();
},
async leave(data) {
pageTransitionIn(data, this)
await delay(1200)
data.current.container.remove();
},
async enter(data) {
pageTransitionOut(data, this);
},
async beforeEnter(data) {
ScrollTrigger.getAll().forEach((x) => x.kill());
console.log('destroying everything');
locoScroll.destroy(); // Optional!
initSmoothScroll(data.next.container);
initScripts();
ScrollTrigger.refresh(); // IMPORTANT!
}
},
{ // Optional
name: 'to-home',
from: {
},
to: {
namespace: ['first-page']
},
once(data) {
// do something once on the initial page load
initSmoothScroll(data.next.container);
initScripts();
},
}]
})
function delay(n) {
n = n || 2000;
return new Promise((done) => {
setTimeout(() => {
done();
}, n);
});
}
// Animation - Page transition In
function pageTransitionIn(data, curr) {
let done = curr.async();
const tl = gsap.timeline({ default: { ease: 'power2.inOut' } });
tl.fromTo('.main-wrap', 1, { opacity: 1 }, { opacity: 0 });
tl.fromTo('.btn-hamburger', { opacity: 1 }, { opacity: 0 }, '>');
tl.fromTo('.swipe', 0.75, { x: '-100%' }, { x: '0%', onComplete: done }, '-=0.5',);
}
function pageTransitionOut(data, curr) {
let done = curr.async();
const tl = gsap.timeline({ default: { ease: 'power2.inOut' } });
tl.fromTo('.swipe', 1, { x: '0' }, { x: '100%', stagger: 0.25, onComplete: done });
tl.fromTo(data.next.container, 0.75, { opacity: 0 }, { opacity: 1 });
}