Jump to content
Search Community

Is this the correct way to make different elements globally available with GSAP?

FPNL

Recommended Posts

Posted

Dear community,
 

I've been working with GSAP in combination with WordPress for a while now. I load all GSAP files using wp_enqueue, and everything works as expected. I have a main.js file in my theme/website where I include my script, and it runs exactly the way I want it to.
 

I'm using [data-] attributes to control where and what animations should appear, and that also works well. However, I'd like to ask if this is the recommended or "correct" way to do it.
 

I’m open to tips or suggestions I’d love to hear how you, as a community, would approach this.
 

Also, I’ve added some styles like opacity: 0 directly in my CSS. I did this because when I set those styles using GSAP, I sometimes get a sort of "loading issue" where the element briefly appears before the animation kicks in.

Below is my JavaScript I’m curious to hear your feedback and any improvements you might suggest.

Would you be willing to create a new JavaScript example that shows a better or cleaner way to do this? I know that the jQuery part might not be the best approach.

 

JS:
 

(function($, document) {
	'use strict';

	$(document).ready(function () {

		gsap.registerPlugin(ScrollTrigger, ScrollSmoother, SplitText);
		gsap.defaults({
			duration: 1,
			ease: 'expo.out'
		});

		ScrollSmoother.create({
			wrapper: '.js-smooth-scroll-outer',
			content: '.js-smooth-scroll-inner',
			smooth: 1,
			smoothTouch: 0.1,
			effects: true
		});

		var splitEls = gsap.utils.toArray('[data-split-text]');

		splitEls.forEach(function(el) {
			var split = new SplitText(el, {
				type: 'lines, words',
				linesClass: 'split-text',
				wordsClass: 'split-text-inner'
			});
			el._split = split;
			gsap.set(split.words, { y: 150, opacity: 0 });
		});

		var batchSelectors = [
			'[data-fade-top]',
			'[data-fade-bottom]',
			'[data-fade-left]',
			'[data-fade-right]',
			'[data-fade-in]',
			'[data-scale-up]',
			'[data-split-text]'
		].join(',');

		ScrollTrigger.batch(batchSelectors, {
			interval: 0.1,
			batchMax: 20,
			start: 'top 90%',
			once: true,
			onEnter: function(batch) {

				var splitEls = batch.filter(el => el._split);
				var otherEls = batch.filter(el => !el._split);

				splitEls.forEach(el => {
					gsap.to(el, {
						opacity: 1,
						duration: 0.3,
						ease: 'power1.out'
					});

					gsap.to(el._split.words, {
						y: 0,
						opacity: 1,
						duration: 1.2,
						ease: 'expo.out',
						stagger: 0.1,
						delay: 0.3
					});
				});

				if (otherEls.length) {
					gsap.to(otherEls, {
						x: 0,
						y: 0,
						scale: 1,
						opacity: 1,
						delay: 0.5,
						stagger: 0.1
					});
				}
			}
		});

	});
})(jQuery, document);



CSS:

[data-fade-top] {
	transform: translateY(-80px);
	will-change: transform;
}

[data-fade-bottom],
[data-fade-top] {
	opacity: 0;
	will-change: transform, opacity;
}

[data-fade-bottom] {
	transform: translateY(80px);
	will-change: transform;
}

[data-fade-left] {
	transform: translateX(-80px);
	will-change: transform;
}

[data-fade-left],
[data-fade-right] {
	opacity: 0;
	will-change: transform, opacity;
}

[data-fade-right] {
	transform: translateX(80px);
	will-change: transform;
}

[data-fade-in],
[data-scale-up] {
	opacity: 0;
	will-change: transform, opacity;
}

[data-scale-up] {
	transform: scale(0);
	will-change: transform;
}

[data-split-text] > * {
	overflow: hidden;
}

[data-split-text] {
	opacity: 0;
	will-change: transform, opacity;
}
mvaneijgen
Posted

Hi @FPNL welcome to the forum! 

 

Seems totally fine to me! Instead of using opacity you can set visibility: hidden; as written up here https://gsap.com/resources/fouc/ opacity is not wrong, but this is what GSAP has built for it. 

 

Hope it helps and happy tweening! 

  • Like 1
Posted

Thanks for your response. I myself am looking at structure a bit. Would you or you as a community like to make an example of how to set up the ScrollTrigger cleaner and how this is more acceptable?

Posted

Hi,

 

Your code looks good for me, the only thing that caught my attention is this:

splitEls.forEach(el => {
  gsap.to(el, {
    opacity: 1,
    duration: 0.3,
    ease: 'power1.out'
  });

  gsap.to(el._split.words, {
    y: 0,
    opacity: 1,
    duration: 1.2,
    ease: 'expo.out',
    stagger: 0.1,
    delay: 0.3
  });
});

The splitEls array contains every DOM element with a specific selector, then you create a SplitText instance on each one and set the opacity of the words of that SplitText instance to 0, so every element in that splitEls element is not visible so why are you animating the element and then the SplitText's words array? Are there other child elements in that parent besides the text? If so why not use a Timeline instead of two Tweens one with a delay? Using a manual delay could lead to an bug since you might want to change the duration of the first tween but if you forget to update the delay on the other Tween you'll have a timing issue. Timelines are build for easily sequencing tweens and you also have the powerful position parameter as well:

https://gsap.com/docs/v3/GSAP/Timeline

 

Happy Tweening!

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.
×
×
  • Create New...