Jump to content
Search Community

Animating dynamic content with pagination?

NickWoodward test
Moderator Tag

Recommended Posts

So I've got my card animations working :)

I've got a function to render a card element:

 

const renderJob = ({title, wage, location, description}, element) => {
    const markup =            
    `<div class="job-card">
        <h3 class="job-card__title">${title}</h3> 
        <div class="job-card__content">
            <div class="job-card__wage">${wage}</div> 
            <div class="job-card__location">${location}</div>
            <div class="job-card__description">${description}</div>
        </div>    
        <div class="job-card__footer">
            <button class="job-card__view-btn">View</button>
        
        </div>
    </div>`;
    element.insertAdjacentHTML('beforeend', markup);
}

And a timeline which animates it:

 

var tl = gsap.timeline({defaults: {opacity: 0, ease: 'back'}});

export const animateJobs = () => {
    tl.from('.job-card', { opacity: 0, transformOrigin: "50% 50%", stagger:0.2, ease: 'ease-out'});

}

 

But...

When I get to the bottom of the page my code checks if there are any more elements left to be added, and adds them to the screen if they exist (infinite scroll). But because the older job-cards and the newly added job-cards have the same class name, gsap obviously animates all the cards again, rather than just the new ones that have been added. This leaves me with a blank screen as the elements animate in from the top...

Any advice on how to animate just the newly added elements? I know it's hard to help without a codepen, but I'm using a database and it'll probably take me forever to work out how to replicate it - I was hoping it was a problem someone had come across before and potentially had more general advice?

No worries if not!

Thanks,

Nick

*So far I've tried creating a new timeline each time render is called, but that obviously doesn't work, and I'm now looking into trying to name the elements differently based on when they're added, but haven't got my head round it yet....

 

 

Link to comment
Share on other sites

const renderJob = ({title, wage, location, description}, element, batchNum) => {
    console.log(batchNum);

    const markup =            
    `<div class="job-card job-card-${batchNum}">
        <h3 class="job-card__title">${title}</h3> 
        <div class="job-card__content">
            <div class="job-card__wage">${wage}</div> 
            <div class="job-card__location">${location}</div>
            <div class="job-card__description">${description}</div>
        </div>    
        <div class="job-card__footer">
            <button class="job-card__view-btn">View</button>
        
        </div>
    </div>`;
    element.insertAdjacentHTML('beforeend', markup);
}
    tl.from(`.job-card-${batchNum}`, { opacity: 0, transformOrigin: "50% 50%", stagger:0.23, ease: 'ease-out'})
JobListView.renderJobs(jobs, elements.jobsDisplay, this.searchOptions.index);
JobListView.animateJobs(this.searchOptions.index);

So naming the elements based on when they're added (batchNum) worked, in case this help anyone else?

Would be interested in knowing if there was a better way of doing it though

Link to comment
Share on other sites

Hi Nick,

 

Have you tried clearing the timeline before creating the new .from() instance for the newly added items?

 

https://greensock.com/docs/v3/GSAP/Timeline/clear()

 

The thing is that everytime you add new elements and create a new instance in the timeline, this new instance is added at the end of the timeline, and while the previous elements are no longer in the DOM, they still have a reference to them in the timeline instance, therefore their memory reference is kept as well (with really long lists of data this could lead to a considerably memory leak, so run tests on it) so GSAP doesn't complain, because the objects are there in memory they're not null.

 

In this cases what I normally do is to clear the timeline and pause it at 0 seconds:

 

tl.clear().pause(0);

// When the new elements are in the DOM
tl.from(".my-elements", {/* config */});

// Then when the timeline is played
tl.play();

Also as an alternative you can use .restart(true) instead of pausing at 0 seconds. The reason for that is that once is completed the timeline is still active and is not at zero seconds.

 

Happy Tweening!!!

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