Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
2malH

Problem with killing and reinitialising ScrollTrigger after Single Page App page transition

Recommended Posts

Hi everyone,

 

first of all: Thanks so much for GSAP and all the help you guys are giving here in the forum! I'm blown away by all the possibilities although I just started using it. First time poster, I did my best to search for a similar problem but didn't find anything related, so here I am:

 

As for my problem with ScrollTrigger: If I go to the page that uses ScrollTrigger directly (https://polymorph.media/work/) everything's working fine. But If I navigate between the pages (e.g. go to home and go back or come from a different page) the markers of the elements to be triggered are moved way down.

I'm pretty sure the problem is related to the BarbaJS-like page transition the wordpress theme has implemented and that it doesn't calculate the position correctly. As for the transition there's not much I can change about it. So on the GSAP side: Is this something I can possibly fix with ScrollTrigger.refresh() or ScrollTrigger.update()? Sorry for not providing a codepen since this seems to be a theme related issue.

 

One further question: Is it possible to use ScrollTrigger to auto-hide and show the navbar like Headroom.js (https://wicky.nillia.ms/headroom.js/) does? I'd love to replicate this in GSAP so that there's less to worry about since I'm having the same transition problem as with ScrollTrigger..

 

Edit: Still building the website so I don't mind activating the markers so it visualizes my problem.

  • Like 1

Share this post


Link to post
Share on other sites

That's expected behaviour and indeed is related to Barba.js.

 

When you first load a page, everything is there for ScrollTrigger to pick up. Meaning the DOM does have the elements you pass to ScrollTrigger.

When you navigate to a page using Barba.js, the DOM changes (the old container is removed and the new is added) and ScrollTrigger (or any other script), can't 'listen' the events of these newly added elements. You have to destroy the previous instance of ScrollTrigger and reinitialise it, passing it the new elements. 

 

Barba gives you several hooks to work with (i believe the one you need is beforeEnter) so on that hook, you could use the next object, to find the new elements you want to pass to ScrollTrigger. Something like this:

 

beforeEnter: ({ next }) => {
  const items = next.container.querySelectorAll('whatever you want')
},

You can check the docs, they mention how to work with third party scripts. You need a similar logic with this.

 

Regarding your second question, i believe you don't need ScrollTrigger at all (or either headroom.js). You can use your own function to detect if the user scrolls up or down and then use gsap for the animation of the header. Be sure to hook your function in requestAnimationFrame or gsap.ticker for better performance on scroll. 

  • Like 4

Share this post


Link to post
Share on other sites

  

Thanks a lot @Yannis Yannakopoulos. Your answer really helps as it confirms my assumption. I have now found the events the theme dispatches before and after the transitions (it's not barba js but gsap they're using btw) and I'm listening for transitionOutStart (here I want to kill ScrollTrigger and transitionsDone (here I'll have to initialize ScrollTrigger if used on that page). But I don't really know on how to use ScrollTrigger.kill() as it's not orking as expected.

 

This is how I init ScrollTrigger:

gsap.registerPlugin(ScrollTrigger);

let tl = [];
let projects = ['omrfestival', 'mini', 'porsche', 'boa', 'dinnerberlin'];

for (i = 0; i < projects.length; i++) {
  let tl = gsap.timeline({
    scrollTrigger: {
      trigger: ".portfolio--" + projects[i],
      start: "top 70%",
      end: "top 55%",
    }
  });

  tl.addLabel("animateTitle")
    .fromTo(".portfolio--"+projects[i]+" .portfolio__heading", {opacity: 0, x: -50}, {opacity: 1, x: 0, duration: 0.8})
    .addLabel("animatePlane")
    .fromTo(".portfolio--"+projects[i]+"  .portfolio-img__plane", {opacity: 0, scaleX: 0, transformOrigin:'0% 0%', ease: "expo. out"}, {opacity: 1, scaleX: 1, duration: 0.5}, "-=0.3")
    .addLabel("animateImage")
    .fromTo(".portfolio--"+projects[i]+"  .portfolio-img__image", {opacity: 0, x: -10}, {opacity: 1, x: 0, duration: 0.6}, "-=0.2")
    .addLabel("animateDesc")
    .fromTo(".portfolio--"+projects[i]+"  .portfolio__desc", {opacity: 0, x: -10}, {opacity: 1, x: 0, duration: 0.6}, "-=0.2")
    .addLabel("animateCTA")
    .fromTo(".portfolio--"+projects[i]+"  .portfolio__cta", {opacity: 0, x: -10}, {opacity: 1, x: 0, duration: 0.6}, "-=0.2");
}

 

And here's the eventListener

(function($) {
  function exitPage() {
    console.log("sempliceTransitionOutStart");
    if (tl !== undefined) {
      tl.kill();
      console.log("kill ScrollTrigger");
    }
  }
  function transitionsDone() {
    console.log("sempliceTransitionsDone");
  }

  window.addEventListener("sempliceTransitionOutStart", exitPage );
  window.addEventListener("sempliceTransitionsDone", transitionsDone );
})(jQuery);

 

In the console it show me that the kill section is beeing called but it doesn't destroy it as expected. I've tried both: tl.kill() and ScrollTrigger.kill(). None of them is working. What am I doing wrong?

 

Thanks so much for the help! :)

 

PS: I know that the code above can be optimized. I'm just strating to get into JS. I think utils.toArray() is what I'll have to look into next, right? :)

Share this post


Link to post
Share on other sites

Welcome to the GreenSock forums!

 

On 6/7/2020 at 4:40 AM, 2malH said:

Is it possible to use ScrollTrigger to auto-hide and show the navbar like Headroom.js (https://wicky.nillia.ms/headroom.js/) does? I'd love to replicate this in GSAP so that there's less to worry about since I'm having the same transition problem as with ScrollTrigger..

Definitely! It's quite straightforward:

See the Pen mdVyPvK by GreenSock (@GreenSock) on CodePen

 

6 hours ago, 2malH said:

In the console it show me that the kill section is beeing called but it doesn't destroy it as expected. I've tried both: tl.kill() and ScrollTrigger.kill(). None of them is working. What am I doing wrong?

What do you mean "doesn't destroy it as expected"? Can you please create a minimal version of the demo?

 

6 hours ago, 2malH said:

PS: I know that the code above can be optimized. I'm just strating to get into JS. I think utils.toArray() is what I'll have to look into next, right? :)

Perhaps my article on animating efficiently can be of use. It talks about how to use functions, methods, and control functions to write animation code more efficiently. 

  • Like 4

Share this post


Link to post
Share on other sites

@2malH i also don't get the doesn't destroy it as expected part. However to give you a clue on what's happening and maybe you can work it out, the selectors you're using (.portfolio__heading, .portfolio-img__plane) need to be reselected  after each page transition. 


What i'd suggest is wrap the whole logic of initialising your timeline & ScrollTrigger,  in a function, or a Class which, would have some init & destroy methods. On init you could pass as arguments the elements you want to animate and on the according event (when the new DOM is added on the page) you could re-run init to grab the new elements added on the page and pass them to gsap (after destroying the previous instance).

 

That being said and given the fact that you use Semplice, maybe it's a whole lot easier for you. Checked their docs to find the relevant events, but i came up with this:  https://help.semplice.com/hc/en-us/articles/360035699552-Single-Page-App-Behavior. So there is an option to run some custom code either once or after each page transition. So maybe you could try adding your code with that option enabled (after each page transition) and see if it works.  

 

 

  • Like 3

Share this post


Link to post
Share on other sites

Like the others, I wasn't quite sure what you meant so it'd be great to see a reduced test case but I did want to mention a few things:

  1. If you kill() an animation that created a ScrollTrigger, that does NOT automatically kill the ScrollTrigger instance too because those are distinct. That was intentional. A user could create a ScrollTrigger instance that has various callbacks and ALSO associate an animation with that ScrollTrigger, but they may still want the scroll-related callbacks to fire despite the animation being killed. If you want to kill the ScrollTrigger instance, you have a few options: 
    let animation = gsap.to(... {
      scrollTrigger: {
        ...
        id: "my-id"
      }
    });
    
    // either use the ID:
    ScrollTrigger.getById("my-id").kill();
    
    //or the animation's scrollTrigger property:
    animation.scrollTrigger.kill();

     

  2. I wonder if you were literally calling the undocumented ScrollTrigger.kill() (the static method) instead of the instance's kill() method. The static ScrollTrigger.kill() method literally kills ScrollTrigger completely, so it won't ever work again on that page. It was undocumented intentionally - it's more for our own troubleshooting purposes. So make sure you're calling kill() on the actual ScrollTrigger instance that you want to kill (as shown above). 
  • Like 4

Share this post


Link to post
Share on other sites

@GreenSock point 1 makes perfect sense.

 

Question: is there a best practice you'd suggest for handing multiple instances on the same page? Performance wise, could we reach a pitfall? 

Share this post


Link to post
Share on other sites
13 minutes ago, Yannis Yannakopoulos said:

@GreenSock point 1 makes perfect sense.

 

Question: is there a best practice you'd suggest for handing multiple instances on the same page? Performance wise, could we reach a pitfall? 

Not that I can think of. ScrollTrigger is highly optimized for speed and it does NOT constantly check bounds using something like getClientBoundingRect() which would be expensive. The refresh() which happens on page load, on resize, and when a tab become active/visible again, is where those "expensive" operations are, and then it merely remembers the scroll position values where each start/end is mapped to and ONLY checks those against the current scroll position. It uses a central "scroll" event listener, and it even throttles resize events so that it waits until there's about 0.2 seconds of breathing room between resize events before it actually does its refresh() calculations again. 

 

Basically, it should be pretty dang fast and I can't think of a big bottleneck. Of course if you create 10,000 ScrollTrigger instances on a page, that's gonna require a fair amount of processing :)

  • Like 4

Share this post


Link to post
Share on other sites

@GreenSock you're exactly right with point 2. I was literally just calling ScrollTrigger.kill() in hope to destroy the animation instance I've set before. So that's indeed a great starting point for me.

 

@Yannis Yannakopoulos thanks so much for even digging into the Semplice documentation. I know about the SPA script field and I'm using it for a couple of things already. It's basically listening for the event "sempliceAppendContent" and then calls a function containing the script code I can insert in the admin area. But I'd like to code everything locally into a .js file and embedd it. Makes changing things and testing faster. That being said, you're absolutely right I should create a function or class to control the animations. Since I'm quite a novice, I'll have to read some more on how to accomplish this. @ZachSaucier's article is great especially tip #8 seems to be what I'll have to implement.

 

While setting this up I'm running into some other difficulties you might be able to help me with: In the head section after including ScrollTrigger.min.js via CDN I'm including my customJS file which calls

gsap.registerPlugin(ScrollTrigger);
var tl = gsap.timeline();

function initScrollTrigger() {
  if(tl.ScrollTrigger) {
    tl.ScrollTrigger.kill();
  }
  tl = gsap.fromTo(...);
  ...
}
  

initScrollTrigger();
  
window.addEventListener(
  "sempliceTransitionOutStart",
  function (e) {
    initScrollTrigger();
  },
  false
);

Is this somewhat the right way? Because now it throws me the error "Please gsap.registerPlugin(ScrollTrigger)" which is actually the very first thing I do in the file. I'm kinda lost on how to integrate the whole ScrollTrigger part in an external JS.

 

Edit: Again: I' sorry for not providing a codepen but it's this problem seems to be deeply connected to a lot things, I'm finding it hard to replicate it in a minimal version.

Share this post


Link to post
Share on other sites
2 minutes ago, 2malH said:

it throws me the error "Please gsap.registerPlugin(ScrollTrigger)" which is actually the very first thing I do in the file.

Sounds like the ScrollTrigger file isn't loading. You can check in the network panel of your dev tools.

 

3 minutes ago, 2malH said:

I'm kinda lost on how to integrate the whole ScrollTrigger part in an external JS.

We have helpful install videos that can help you getting things up and running: greensock.com/install

  • Like 2

Share this post


Link to post
Share on other sites

@2malH can you also please verify that you're using version 3.3.1?

Share this post


Link to post
Share on other sites

@GreenSock, @ZachSaucier

I thought that I'd have followed the installation instructions just right but it's not working. :-/

 

This is how I'm loading GSAP.

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.1/gsap.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.1/CSSRulePlugin.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.1/ScrollToPlugin.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.1/ScrollTrigger.min.js"></script>
  <script src="https://polymorph.media/wp-content/themes/polymorph/assets/js/polymorph.min.js"></script>
<!-- I've also tried to register the plugin right away in the head section but it didn't remove the errors
<script>gsap.registerPlugin(ScrollTrigger);</script>
-->
</head>

 

polymorph.min.js - this is where I'd like to place the GSAP related code and register the plugin.

gsap.registerPlugin(ScrollTrigger);
var tl = gsap.timeline();


function initScrollTrigger() {
  console.log("initScrollTrigger");

  if(tl.ScrollTrigger) {
    tl.ScrollTrigger.kill();
  }

  tl = gsap.timeline({
    scrollTrigger: {
    trigger: ".portfolio--omrfestival",
    start: "top 70%",
    end: "top 55%",
    markers: true,
    }
  });

  tl.addLabel("animateTitle").fromTo(".portfolio--omrfestival .portfolio__heading", {opacity: 0, x: -50}, {opacity: 1, x: 0, duration: 0.8});

}

initScrollTrigger();

window.addEventListener(
  "sempliceTransitionsDone",
  function (e) {
    initScrollTrigger();
  },
  false
);

 

These are the errors it throws

Please gsap.registerPlugin(ScrollTrigger) ScrollTrigger.min.js:10:13807
Uncaught TypeError: can't access property "indexOf", i is undefined
    C https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.1/ScrollTrigger.min.js:10
    init https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.1/ScrollTrigger.min.js:10
    ScrollTrigger https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.1/ScrollTrigger.min.js:10
    create https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.1/ScrollTrigger.min.js:10
    Aa https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.1/gsap.min.js:10
    Timeline https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.1/gsap.min.js:10
    timeline https://cdnjs.cloudflare.com/ajax/libs/gsap/3.3.1/gsap.min.js:10
    initScrollTrigger https://polymorph.media/wp-content/themes/polymorph/assets/js/polymorph.min.js:12
    <anonymous> https://polymorph.media/wp-content/themes/polymorph/assets/js/polymorph.min.js:52

 

Edit: Added the comment that I've also tried to register the plugin right within the head section without success

Share this post


Link to post
Share on other sites

It's almost impossible to troubleshoot blind like this - can you please provide a reduced test case in CodePen? I'd love to help identify the problem, but my hands are tied right now. 

 

One shot in the dark - I bet you've got your code running BEFORE the <body> tag. That'd mean your DOM isn't even available yet, so please make sure you're putting the GSAP-related code at the BOTTOM of the <body> (or just below it). 

  • Like 2

Share this post


Link to post
Share on other sites

@GreenSock you've nailed it, that was it. 🤦‍♂️ Thanks a lot. I'll try to take it from here. I even managed to kill the ScrollTriggers I intended to. So thanks a lot for that!

 

One last question:

Given this site structure with multiple pages and multiple containers each holding different elements I want to animate. What's the best practice to set this up? Should I setup a timeline for each container or one for each page?

 

page1
  container--1
    container__title
    container__image
    container__text
  container--2
    container__title
    container__image
    container__text
  container--3
    container__title
    container__image
    container__text

page2
  container--a
    container__title
    container__image
    container__text
  container--b
    container__title
    container__image
    container__text
  container--c
    container__title
    container__image
    container__text

 

Share this post


Link to post
Share on other sites
2 hours ago, 2malH said:

Should I setup a timeline for each container or one for each page?

It depends on your needs. Usually it's best to do per section but depending on the effect you need it might make sense to use one big timeline.

 

Again, I recommend my animating efficiently article

  • Like 1

Share this post


Link to post
Share on other sites

Also, you had a typo in your code - you used an uppercase "S" instead of lowercase: 

// BAD
tl.ScrollTrigger.kill();

// GOOD
tl.scrollTrigger.kill();

 

  • Like 2

Share this post


Link to post
Share on other sites

Hi there , I'm definitely having the same issue and thank god I found this forum because I was thinking i was going insane trying to find the bug. So basically as

On 6/7/2020 at 2:09 PM, Yannis Yannakopoulos said:

When you first load a page, everything is there for ScrollTrigger to pick up. Meaning the DOM does have the elements you pass to ScrollTrigger.

When you navigate to a page using Barba.js, the DOM changes (the old container is removed and the new is added) and ScrollTrigger (or any other script), can't 'listen' the events of these newly added elements. You have to destroy the previous instance of ScrollTrigger and reinitialise it, passing it the new elements. 

I'm guessing this is why my ScrollTrigger is not working as expected with BarbaJS as I navigate from the homepage to about page on my portfolio site everything else works as expected but sometimes the markers are out of their places . Which is even more weird is that sometimes the behaviour is actually perfect when viewed on mobile and then other times not on mobile but i'm guessing it has something to do with the Barba Removing of my elements so basically what you advise me to do is make reference variables to the elements I want to animate with GSAP and then call a function in beforeAfter () hook to redeclare those variables to new elements that Barba has swapped in and then pass them to the gsap animations. Or what do ye( @GreenSock @Yannis Yannakopoulos, @2malH) mean kill the scrollTrigger instance , why do I need to do that , is that just an easier way of doing what I've just implied above??

 

homepage.js

//Variable Declarations and Function Definitions 
let viewBox = ""
heading_Pos = [0, 0]
displayState = ""
hamburger_display_button = Array.from($('.mobile_nav_sticky'))[0]
opened_nav_buttons = document.querySelector('.options')
logo = $(".Actual_Logo_Svg")
// Morphing Circles and ellipses to paths to be able to morph them and checking the viewbox for device size
MorphSVGPlugin.convertToPath("ellipse");
shapes = Array.from($('.Logo_In_Shapes path'))

const homeInit = () => {
    viewBox = "",
        heading_Pos = [0, 0],
        displayState = ""
    hamburger_display_button = Array.from($('.mobile_nav_sticky'))[0]
    opened_nav_buttons = document.querySelector('.options')
    logo = $(".Actual_Logo_Svg");
    // Morphing Circles and ellipses to paths to be able to morph them and checking the viewbox for device size
    MorphSVGPlugin.convertToPath("ellipse");
    shapes = Array.from($('.Logo_In_Shapes path'))
}

const logo_tl_func = () => {
    let logo_tl = gsap.timeline({
        onComplete: moveLogo,
    })
    // Morphing into the Logo
    logo_tl.from(shapes, 1, {
        y: -600,
        autoAlpha: 0,
        ease: "bounce",
        stagger: 0.15
    })
    logo_tl.to(shapes, 1, {
        fill: '#F0C368',
        stagger: 0.05
    })
    let firstAnimation = gsap.to('.shapes', {
        duration: 2,
        morphSVG: ".Logo_Proper_Background"
    });
    let secondAnimation = gsap.to('.textShape', {
        duration: 2,
        fill: '#1D373F',
        morphSVG: ".Logo_Proper_Text"
    });
    logo_tl.add([firstAnimation, secondAnimation])
}

const changeViewBox = media_query => {
    media_query.matches ? viewBox = "-150 -180 2495 890" : viewBox = "-150 -350 3574 880"
    media_query.matches ? heading_Pos = [-511, -15] : heading_Pos = [-1540, 40];
    media_query.matches ? displayState = "none" : displayState = "block"
}

const moveLogo = () => {
    gsap.to(logo, {
        attr: { viewBox: viewBox },
        duration: 3
    })
    fadeInHeadingAndLinks();
}

const fadeInHeadingAndLinks = () => {
    gsap.to('.nav_links', {
        display: displayState,
        scale: 1,
        duration: 3
    })
    gsap.to('.logo_heading', {
        display: "block",
        x: heading_Pos[0],
        y: heading_Pos[1],
        // scale:1,
        duration: 3
    })
    gsap.to('.mobile_nav_sticky', {
        display: "block",
        scale: 1,
        duration: 5
    }, "+=.7")
}

const pageTransition = () => {
    var tl = gsap.timeline();
    tl.set('.loading_container img', {
        scale: 0.3
    })
    tl.to('.loading_container', {
        duration: 1.2,
        width: "100%",
        left: "0%",
        ease: "circ.out",
    })
        .to('.loading_container img', {
            scale: 0.6,
            duration: 1
        }, "-=1.2")

        .to('.loading_container', {
            duration: 1.2,
            width: "0%",
            right: "0%",
            ease: "circ.out",
        })
        .to('.loading_container img', {
            scale: 0.3,
            duration: 1.2
        }, "-=1.3")
}

// Helper Functions

const delay = (ms) => {
    return new Promise(resolve => setTimeout(resolve, ms));
}

// Initialization Methods
$(document).ready(() => {
    window.matchMedia("(max-width: 600px)").matches ? logo.attr('viewBox', '-350 -700 1274 1680') : logo.attr('viewBox', '-680 -380 2074 1080')
    var viewbox = window.matchMedia("(max-width: 600px)")
    changeViewBox(viewbox)
})

hamburger_display_button.onclick = () => {
    opened_nav_buttons.classList.toggle('open')
}

barba.init({
    sync: true,
    transitions: [{
        name: 'transition-base',
        preventRunning: true,
        timeout: 5000,
        async leave() {
            const done = this.async();
            pageTransition();
            await delay(1000);
            done();
        },
        async enter() {
            window.scrollTo(0, 0);
        },
    }],
    views: [
        {
            namespace: 'home',
            afterEnter() {
                homeInit()
                window.matchMedia("(max-width: 600px)").matches ? logo.attr('viewBox', '-350 -700 1274 1680') : logo.attr('viewBox', '-680 -380 2074 1080')
                let viewbox = window.matchMedia("(max-width: 600px)")
                changeViewBox(viewbox)
                logo_tl_func();
                hamburger_display_button.onclick = () => {
                    opened_nav_buttons.classList.toggle('open')
                }
            },
        },
        {
            namespace: 'about',
            afterEnter() {
                aboutInit()
                face_tl_func()
                scroll_p_tl_func()
                scroll_skills_tl_func()
                scroll_facts_tl_func()
            },
        }
    ],
});

// //Global Hooks 
// barba.hooks.leave(() => {
//     const done = this.async();
//     pageTransition();
//     await delay(1000);
//     done();
// })
// barba.hooks.enter(() => {
//     window.scrollTo(0, 0);
// })

 

about.js

// Variable Declarations and Function Definitions
let factsContainer_sm = document.querySelector(".factsContainer_sm")

const aboutInit =() => {
    factsContainer_sm = document.querySelector(".factsContainer_sm")
    let head = document.getElementsByTagName('head')[0],
    link = document.createElement('link')
    link.rel = 'stylesheet'
    link.href= "../../Resources/CSS/about.css"
    head.appendChild(link);
}

const face_tl_func = () => {
    let face_tl = gsap.timeline(),
        paths = document.querySelectorAll('.My_Face path'),
        filledYellowElements = ['.Main_Hair_Part', '.Eyeball_2', '.Eyeball_1', '.Nostril_1', '.Nostril_2', '.Tongue_Part'],
        filledNavyElements = ['.Pupil_2', '.Pupil_1'];
    face_tl.set(filledNavyElements, { fill: 'unset' }),
        face_tl.set(filledYellowElements, { fill: 'unset' }),
        face_tl.fromTo(paths, { drawSVG: "0%" }, { duration: 1, drawSVG: "100% ", stagger: 0.15 })
    let firstAnimation = gsap.to(filledYellowElements, {
        duration: 2,
        ease: "slow",
        fill: '#F0C368'
    }, "-=.7"),
        secondAnimation = gsap.to(filledNavyElements, {
            duration: 2,
            ease: "bounce",
            fill: '#1D373F'
        }, "-=.7")
    face_tl.add([firstAnimation, secondAnimation])
}


const scroll_p_tl_func = () => {
    let scroll_tl = gsap.timeline({
        scrollTrigger: {
            trigger: '.content',
            start: "top center",
            end: "+=1000",
            markers: true,
            scrub: true
            // pin: true
        }
    })
    scroll_tl.to('.first', {
        transform: "rotateX(50deg) rotateZ(331deg) translateX(42px)",
        duration: .5,
    }),
        scroll_tl.to('.flag', {
            scale: 1
        }, '-=.1'),
        scroll_tl.addLabel("first_down")
    scroll_tl.to('.second', {
        transform: "rotateX(50deg) rotateZ(331deg) translateX(42px)",
        duration: 2,
    }, "first_down-=.1")
    scroll_tl.addLabel("second_down")
    scroll_tl.to('.third', {
        transform: "rotateX(50deg) rotateZ(331deg) translateX(42px)",
        duration: 2,
    }, "second_down-=.01")
}


const scroll_skills_tl_func = () => {
    let scroll_tl = gsap.timeline({
        scrollTrigger: {
            trigger: '.skillsContainer',
            start: "top center",
            markers: true,

        }
    }),
        barWidth = "",
        bars = [...document.querySelectorAll('.bar')]
    bars.map(bar => {
        barWidth = bar.dataset.width;
        let barAnimation = gsap.to(bar, {
            width: barWidth,
            duration: 1,
            delay : .2
        }),
            percentageAniamtion = gsap.to('.percentage', {
                scale: 1,
            })
        scroll_tl.add([barAnimation, percentageAniamtion]);
    })

}

const scroll_facts_tl_func = () => {
    let scroll_tl = gsap.timeline({
        scrollTrigger: {
            trigger: '.factsContainer',
            start: "top center",
            // pin: true,
            scrub: true,
            end: "+=300",
            markers: true,
        }
    }),
        facts = [...document.querySelectorAll('.fact')]
    scroll_tl.to('.factsContainer h2', {
        scale: 1.5,
        duration: 1,
        ease: "slow"
    })
    scroll_tl.to(facts, {
        xPercent: -85 * (facts.length - 1),
        scrollTrigger: {
            trigger: ".factsContainer_sm",
            start: "center center",
            pin: true,
            // pinSpacing:false,
            markers: true,
            scrub: 1,
            snap: 1 / (facts.length - 1),
            // base vertical scrolling on how wide the container is so it feels more natural.
            end: () => `+=${factsContainer_sm.offsetWidth}`
        }
    });
}


// //Initialization Methods
// aboutInit()
// face_tl_func()
// scroll_p_tl_func()
// scroll_skills_tl_func()
// scroll_facts_tl_func()

Here's my homepage - https://adamoceallaigh.netlify.app/

and here's my about page - https://adamoceallaigh.netlify.app/about.html

Share this post


Link to post
Share on other sites

@adamoc Please stick to the thread that you created. We're pretty good about responding to things :) There's no point in cross-posting in other threads.

Share this post


Link to post
Share on other sites

@adamoc that's a lot of code to digest easily. Maybe if you could provide a reduced case, i could understand better.

 

However, taking a quick look at your code i think your main issue is more in the architecture of the code, than it is about ScrollTrigger.

I noticed you are initialising Barba.js inside your homepage.js file.  Not sure what your structure is, but provided that homepage.js is only used on homepage, that approach is wrong. 

 

You should have something like a main.js file, which will contain all your Barba.js related functions and then use Views for any page specific logic.

 

Take a look at the docs, they have some great details.  

  • Like 3

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×