Jump to content
Search Community

Possible for Gsap to be triggered by flickity (ie .is-selected)

Tony Astley test
Moderator Tag

Go to solution Solved by akapowl,

Recommended Posts

Hopefully a quick question. I have a flickity.js banner system with GSAP animated elements within each banner. However I'm struggling to get GSAP to work on anything other than the first banner. 

 

I've tried targeting the elements in the current banner:

 

const targets = gsap.utils.toArray('.is-selected .animatedBannerElement[gsap-animated]');

However this only works for the first banner? When the second banner becomes visible and has .is-selected class added nothing happens.

 

I've tried calling ScrollTrigger.refresh(); from flickity.js but that doesn't work either?

 

Am I missing something obvious?

Link to comment
Share on other sites

It's essentially a gap.to animation.

The starting point is set by the css, a few of the attributes are called in from the elements markup (I tried to recreate something similar to AOS).

 

/*All other elements*/
        const targets = gsap.utils.toArray('.is-selected *[data-gsap-animated]');
            targets.forEach(target => {

                /*Get attributes from element*/
				animation = target.getAttribute('data-gsap-animated');
                delay = target.getAttribute('data-gsap-delay');
                duration = target.getAttribute('data-gsap-duration');
                start = target.getAttribute('data-gsap-start');
                end = target.getAttribute('data-gsap-end');

                /*Set defaults if none found*/
                if(!delay) { delay = 0; }
                if(!duration) { duration = 0.5; }
                if(!start) { start = "top 95%"; }
                if(!end) { end = "top 60%"; }

                /*Manipulate ScrollTrigger if in viewport*/
                if (isInViewport(target) ) {
					scrollSettings = {
                        trigger: target,
					};
				} else {
					scrollSettings = {
                        trigger: target,
						start: start,
						end: end,
						scrub: 0.5,
                    };
				}

                /*Manipulate Clip Path if animation contains wipe*/
                if(animation.includes("wipe")){
                    clipPathSettings = "polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)";
                } else {
                    clipPathSettings = "";
                }

                /*Animate the element*/
				gsap.to(target, {
					opacity: 1,
					scale: 1,
					duration: duration,
					delay: delay,
					transform: "none",
                    clipPath: clipPathSettings,
					scrollTrigger: scrollSettings,
				});

                /*Reset to default */
                delay = 0;
                duration = 0.5;
                start = "top 90%";
                end = "top 60%";

            });
        }

 

Link to comment
Share on other sites

Flickity adds a class to the active slide of '.is-selected', what I want to happen is when that class gets added the animations to start. Currently this works for the first item, but when the new slides are show and the class is added no animation occurs.

 

I'm guessing it's something to do with the markup flickity adds to the Dom not being picked up by gsap.

Link to comment
Share on other sites

Ok. Well, I still don't understand what this is supposed to look like, but it seems that the issue you are having is that the tween doesn't fire when the class is added or removed. That is expected behavior since you need to tell the tween when to fire. If flickity provides a callback for when a new item is selected, you could put the logic in there. Alternatively, you can use the JS Mutation Observer to watch for when the class changes.

Link to comment
Share on other sites

  • Solution

Hey there!

 

I'm not 100% sure either about what it is you ary trying to do...

 

33 minutes ago, Tony Astley said:

Flickity adds a class to the active slide of '.is-selected', what I want to happen is when that class gets added the animations to start. Currently this works for the first item, but when the new slides are show and the class is added no animation occurs

 

...but this doesn't sound like you need ScrollTrigger for that - I might be misunderstanding though.

 

If you want to animate something whenever flickity changes slides, you might want to have a look at their events instead...

 

https://flickity.metafizzy.co/events.html

 

 

... probably something along the lines the example in their docs shows.

// vanilla JS
var flkty = new Flickity( '.carousel', {
  on: {
    ready: function() {
      console.log('Flickity is ready');
    },
    change: function( index ) {
      console.log( 'Slide changed to' + index );
    }
  }
});

 

 

...because if you create the array with all the elements once on load like you do, it will of course only have the elements that meet those requirements on load; it can not know about any elements that will be meeting those requirements in the future.

 

  • Like 2
Link to comment
Share on other sites

Hello, this pretty much achieves what I was looking for:

 

.flickity-enabled *[data-banner-animated] {
	transform-origin: left center;
	transition: all;
	transition-duration: 0.5s;
	transition-delay: 0;

	&[data-banner-animated='fade-in'] {
		opacity: 0;
	}

	&[data-banner-animated='fade-left'] {
		opacity: 0;
		transform: translateX(calc(-30px));
	}
	&[data-banner-animated='fade-right'] {
		opacity: 0;
		transform: translateX(calc(30px));
	}
	&[data-banner-animated='fade-down'] {
		opacity: 0;
		transform: translateY(calc(-30px));
	}
	&[data-banner-animated='fade-up'] {
		opacity: 0;
		transform: translateY(calc(30px));
	}

	&[data-banner-animated='scale-left'] {
		opacity: 0;
		transform-origin: center left;
		transform: scaleX(0);
	}
	&[data-banner-animated='scale-right'] {
		opacity: 0;
		transform-origin: center right;
		transform: scaleX(0);
	}
	&[data-banner-animated='scale-down'] {
		opacity: 0;
		transform-origin: top left;
		transform: scaleY(0);
	}
	&[data-banner-animated='scale-up'] {
		opacity: 0;
		transform-origin: bottom left;
		transform: scaleY(0);
	}

	&[data-banner-animated='wipe-left'] {
		opacity: 0;
		clip-path: polygon(100% 0%, 100% 0%, 100% 100%, 100% 100%);
	}
	&[data-banner-animated='wipe-right'] {
		opacity: 0;
		clip-path: polygon(0% 0%, 0% 0%, 0% 100%, 0% 100%);
	}
	&[data-banner-animated='wipe-down'] {
		opacity: 0;
		clip-path: polygon(0% 0%, 100% 0%, 100% 0%, 0% 0%);
	}
	&[data-banner-animated='wipe-up'] {
		opacity: 0;
		clip-path: polygon(0% 100%, 100% 100%, 100% 100%, 0% 100%);
	}

	&[data-banner-animated='zoom-up'] {
		opacity: 0;
		transform: scale(0.8);
	}
	&[data-banner-animated='zoom-down'] {
		opacity: 0;
		transform: scale(1.2);
	}


}

.is-selected *[data-banner-animated] {
	opacity: 1;
	scale: 1;
	transform: none;

	&[data-banner-animated='wipe-left'],
	&[data-banner-animated='wipe-right'],
	&[data-banner-animated='wipe-down'],
	&[data-banner-animated='wipe-up'] {
		clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
	}

}

 

Edited by Tony Astley
Should only really apply classes when flickity is loaded to avoid permanently hidden elements if js fails.
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...