Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...
ajmnz

Noticeable lag on background-image fade

Recommended Posts

Hello,

First of all, sorry for just copying and pasting the whole project, but I didn't have enough time to replicate the issue in a minimalistic way. Hope it's useful to solve the problem I'm facing.

 

I'm currently working on my personal site which its homepage consists of a slider. When the slide changes, a div covering the whole viewport with a background image should also change accordingly. It is done using gsap.timeline() and as you can notice, there's a really noticeable amount of lag when the animation happens. Without the background change, everything is smooth.

 

Tested on a 2018 15inch Macbook Pro running macOS Catalina 10.15.6 on Google Chrome v84.0.4147.89 (laggy), Firefox v79.0 (really really laggy) and Safari v13.1.2 (somehow smooth).

 

Thank you in advance,

Arnau.

 

ps: I was just testing and I know the background image is incredibly stretched, already tried with a properly sized one and same results.

ps2: As of now, only the next page button works ("següent").

Link to comment
Share on other sites

Hey ajmnz and welcome to the GreenSock forums.

 

For these sorts of things it's best to create the animation at the start and use control methods to control the animation. Not only will this perform better but it will also solve logical issues (for example try clicking the next button multiple times in a row - it breaks). I talk extensively about how to structure that sort of thing in my article about animating efficiently. I think you'll learn a lot from that article :) 

 

Why do you need to clone the background? That's an intensive operation. I recommend just including all the DOM elements you need on page load.

 

Functions within functions when those outer functions are called multiple times is also something to avoid.

 

Side notes:

  • We recommend using xPercent and yPercent over x: "100%", etc.
  • Since you have the same CustomEase every time it's probably best to create the CustomEase once and then reuse the same instance later.
  • You'd benefit from using GSAP 3's defaults functionality.
Link to comment
Share on other sites

Hey Zack!

 

Thanks for the fast reply. I will definitely take a look at that article and surely it'll help me understand better how to manage GSAP efficiently.

 

On the other hand, by 

4 minutes ago, ZachSaucier said:

Functions within functions when those outer functions are called multiple times is also something to avoid.

you mean the callback firing within onComplete, right?

 

I really appreciate this feedback too, didn't know of xPercent and yPercent!

5 minutes ago, ZachSaucier said:
  • We recommend using xPercent and yPercent over x: "100%", etc.
  • Since you have the same CustomEase every time it's probably best to create the CustomEase once and then reuse the same instance later.

 

And finally, if that's not an inconvenience, could you please specify what do you specifically mean by this statement?

6 minutes ago, ZachSaucier said:

You'd benefit from using GSAP 3's defaults functionality.

 

Many thanks for the help and the quick and useful reply!

Link to comment
Share on other sites

1 minute ago, ajmnz said:

you mean the callback firing within onComplete, right?

I mean changeCurrent is placed within the click listener. Avoid creating functions within functions like that.

 

2 minutes ago, ajmnz said:

specifically mean by this statement?

9 minutes ago, ZachSaucier said:

You'd benefit from using GSAP 3's defaults functionality.

 

Link to comment
Share on other sites

Hi again, 

After reading the article you recommended me and applying some of the suggestions, this is what I came up with.

// Animate title outline
    const animOutline = () => {

        const title_ease = 'power2.in',
            title_stag = 0.02,
            title_anim = gsap.timeline({
                defaults: {
                    ease: title_ease,
                    stagger: title_stag
                },

            });

        title_anim
            .to(".title-outline .char", {
                yPercent: '+=100'
            })

        return title_anim;

    }

    // Animate title fill
    const animFill = () => {
        const title_ease = 'power2.in',
            title_stag = 0.02,
            title_anim = gsap.timeline({
                defaults: {
                    ease: title_ease,
                    stagger: title_stag
                },

            });

        title_anim
            .to(".title-fill .char", {
                yPercent: '+=100'
            })

        return title_anim;
    }

    // Animate image
    const animSlide = () => {
        const slide_ease = CustomEase.create('custom', '0.76, 0, 0.24, 1'),
            slide_dur = 0.6,
            slide_anim = gsap.timeline({
                defaults: {
                    ease: slide_ease,
                    duration: slide_dur
                },

            });

        slide_anim
            .to(".image-wrapper img", {
                xPercent: '-=100'
            })

        return slide_anim;
    }

    // Create and add timelines to the master one
    const master = gsap.timeline({
            paused: true 
        })
        
    master.add(animOutline())
          .add(animFill())
          .add(animSlide())

    
    $('.slider-nav').on('click', function (ev) {
        
        if (ev.target.classList.contains('slider-previous')) { // If previous slide
            master.reverse()
        } else if (ev.target.classList.contains('slider-next')) { // If next slide
            master.play()

        }
    })

 

The thing is that I need that xPercent and yPercent to increase anytime that the master timeline is played or reversed. What I suspect is that, if I want to keep using play() and reverse(),  I need to somehow update the target, but I don't know how. Maybe by remaking the whole timeline, but that would kill the efficiency  pointed out later.

 

Hope that snippet is enough, if not, I'll try to recreate it in a codepen.

Link to comment
Share on other sites

Please do make a minimal demo :) It will help things be less abstract as I have no idea what your end goal is.

Link to comment
Share on other sites

Updated the one from yesterday: 

See the Pen JjXwbOg by ajmnz (@ajmnz) on CodePen

 

What I want to achieve is having that xPercent and yPercent values (inside animFill, animOutline and animSlide) to actually increment (+=100) every time the master timeline is played or reversed.

Maybe there's a way to redeclare the target before calling play() and reverse() or something like that?

Link to comment
Share on other sites

Hey ajmnz.

 

1 hour ago, ajmnz said:

What I want to achieve is having that xPercent and yPercent values (inside animFill, animOutline and animSlide) to actually increment (+=100) every time the master timeline is played or reversed.

That's not how timelines work. Timelines are meant to be pretty static. There is a repeatRefresh property but that only helps if the whole timeline repeats.

 

I think it'd be better to just create all of your animations at the start and perhaps use the .addPause() method to stop on each section.

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.
×