Jump to content
Search Community

gsap splittext with mouseevent, performance issue on multiple objects

fonveton test
Moderator Tag

Recommended Posts

 gsap.utils.toArray(".text-hover-effect").forEach(element => {
	let text = element.textContent;
	element.innerHTML = '<span class="actual -translate-y-[50%] [&_.split-chars]:overflow-hidden absolute left-0 top-[50%] w-[100%]">' + text + '</span><span class="placeholder [&_.split-chars]:overflow-hidden">' + text + '</span>';

	let placeholder = new SplitText(element.querySelector(".placeholder"), { type: "chars, words, lines", charsClass: 'split-chars', wordsClass: 'split-words', linesClass: 'split-lines' });
	let actual = new SplitText(element.querySelector(".actual"), { type: "chars, words, lines", charsClass: 'split-chars', wordsClass: 'split-words', linesClass: 'split-lines' });
	
	let textHoverTL = gsap.timeline({ paused: true });
	
	gsap.set(actual.chars, { y: '50%', opacity: 0, });

	textHoverTL.to(placeholder.chars, { duration: 0.25, y: '-50%', opacity: 0, stagger: 0.001 })
	.to(actual.chars, { delay: 0.025, duration: 0.25, y: '0%', opacity: 1, stagger: 0.001 }, 0);
	
	element.addEventListener("mouseenter", () => { textHoverTL.play() }, false);
	element.addEventListener("mouseleave", () => { textHoverTL.reverse() }, false);
});

I wrote a short code for text animation and I'm using this class on multiple object on page. The problem I'm having is if there are too many element it becomes a performance issue. I takes 1-2 seconds to load with over 50+ '.text-hover-effect' classes. I know the problem is I'm doing a lot of things before page load and that is what creates performance issues. What I don't know, how to solve this. I tried making all codes start working on hover but that way with multiple classes it's not working how it supposed to be and breaks you you move your cursor swiftly between objects.

 

 const textAnim = {
   in: { duration: 0.15, y: '-25%', opacity: 0, stagger: 0.001 },
   out: { delay: 0.015, duration: 0.15, y: '0%', opacity: 1, stagger: 0.001 }
 };

gsap.utils.toArray(".fx-text-hover-with-child").forEach(el => {
    el.setAttribute('data-fx', el.querySelector(".fx-child").textContent);

    el.addEventListener("mouseenter", () => {
      let child = el.querySelector(".fx-child");

      if (el.getAttribute('data-fx') != 'used') {
        let text = el.getAttribute('data-fx');
        el.setAttribute('data-fx', 'used');

        child.innerHTML = '<div class="actual -translate-x-[50%] -translate-y-[50%] absolute left-[50%] top-[50%] w-[100%]">' + text + '</div><div class="placeholder">' + text + '</div>';

        new SplitText(el.querySelector(".placeholder"), { type: "chars, words, lines", charsClass: 'split-chars', wordsClass: 'split-words', linesClass: 'split-lines' });
        new SplitText(el.querySelector(".actual"), { type: "chars, words, lines", charsClass: 'split-chars', wordsClass: 'split-words', linesClass: 'split-lines' });
      }

      textTL.add(gsap.set(child.querySelectorAll('.actual .split-chars'), { y: '25%', opacity: 0, }));
      textTL.add(gsap.to(child.querySelectorAll('.placeholder .split-chars'), textAnim.in))
      textTL.add(gsap.to(child.querySelectorAll('.actual .split-chars'), textAnim.out, 0))
      textTL.play();
    }, false);

    el.addEventListener("mouseleave", () => {
      textTL.reverse();
    }, false);
});

 

See the Pen xxaWYeG by manidar (@manidar) on CodePen

Link to comment
Share on other sites

I didn't create a codepen because my issue is performance related using same effect multiple times. In my latest project I used this effect on 210 objects and even chrome lags a lot. It adds extra 2-3 seconds to website load time. I would like to know if there is a gsap approach to solve this issue.

Link to comment
Share on other sites

Ok, thanks! This doesn't really look representative of your actual project though. There's no styling. I'll just assume you don't have any filters or blurs that could affect things there. It seems pretty odd that it's adding 2-3 seconds load time. That's a lot. But yeah - I'll stick to what I said before - split the ones in view and then split the others as and when they come into the viewport.

You could use batch for that - https://greensock.com/docs/v3/Plugins/ScrollTrigger/static.batch()

 

Link to comment
Share on other sites

Two more things that could help - adding the span in to the HTML up front instead of with JS, and only getting splitText to split into chars instead of chars, lines and words - you're not using them so they're unnecessary. Same with the class that's being added, this should be all you need.

 

new SplitText(element.querySelector(".actual"), { type: "chars" });

 

  • Like 2
Link to comment
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.
×
×
  • Create New...