Jump to content
Search Community

Scrolltrigger zoom through element and then scroll

seanom test
Moderator Tag

Go to solution Solved by akapowl,

Recommended Posts

Hello, 

 

I'm hoping to get a bit of guidance on direction for an effect I'm trying to achieve. It's been a while (about 3 years) since I've done a GSAP project so doing a lot of reading trying to catch up on what's new. My aim is to replace scroll magic for this task and switch over to scroll trigger. But currently hitting a few stumbling blocks.

 

The interaction I'm trying to create:

  • Scroll the page until a masked image is reached
  • Pin the image and scale the image revealing the section below it
  • Once the animation has finished add a class
    • Revealing additional content
  • Then continue to scroll the page with a fixed background image
    • With the addition of a few more paralax elements within that.

 

I've tried to use the Pinned demo and modify it to add a masked SVG to demonstrate the effect I'm trying to get. 

Doing some research I think I need to be looking at timelines and then adding the ScrollTrigger along the timeline, but I'm struggling to work out how to get one animation to start after the previous one has finished (or just before).

 

I seem to be able to get the individual animations I'm after working but sticking it all together is proving challenging.

 

Can anyone help point me on the right track please, thank you.

 

 

See the Pen dyNGVog by Seanom (@Seanom) on CodePen

Link to comment
Share on other sites

  • Solution

 

 

Hello @seanom

 

Using a timeline certainly is the best way to approach this - but with your approach you are actually making one of the most common ScrollTrigger mistakes; nesting ScrollTriggers inside multiple timeline-tweens. You'd want to avoid that and instead set up the scrollTrigger on the timeline itself.

 

18 hours ago, seanom said:

Doing some research I think I need to be looking at timelines and then adding the ScrollTrigger along the timeline, but I'm struggling to work out how to get one animation to start after the previous one has finished (or just before).

 

You can use the position parameter of the timeline (more info on that right below the video on the linked docs-page) to properly adjust the timing for the individual tweens of yout timeline. But be aware, that durations and the position parameter on ScrollTrigger-tweens and -timelines with a scrub applied do work quite different from those on regular tweens/timelines.

 

 

 

As for the mask-reveal:

@OSUblake made an awesome demo that shows how such a cirlce mask-reveal can be achieved - responsive to resizes and everything included.

 

See the Pen QWyLVLO by osublake (@osublake) on CodePen

 

 

I went ahead and adjusted it a bit so it fits the scenario you described - so you could take this as inspiration for how to achieve your goal.

For the image to remain in place on further scrolling ( in this special scenario ) I found it would be easiest to just have it positioned fixed outside of any section and hidden initially and then simply tween its opacity to 1 when the time has come. Depending on the exact outcome you want for this later on scrolling it might be better to do things differently though.

 

See the Pen 516bd27adc117af3b315d2c5c3833ad1 by akapowl (@akapowl) on CodePen

 

 

Hope this was a bit helpful. Happy tinkering, scrolling and tweening :) 

 

 

Edit:

Because of the image being positioned fixed in the above approach this would of course not work with the image being initially visible through that hole in the black section, so here is a different approach with one image fixed and one absolute inside the section and a switch of opacity between those at the end of the scrubbing timeline ( will lead to a nasty jump with a numerical scrub-value though so the scrub is set to true ). Maybe somebody else has a simpler approach to that.

 

See the Pen 4877d140c4ab7adae0bc666fc7adced8 by akapowl (@akapowl) on CodePen

 

  • Like 4
  • Thanks 1
Link to comment
Share on other sites

  • 2 weeks later...

@akapowl, thank you once again I've spent a good few days playing and think I've got this to a good place, but I wanted to share where I ended up just check on the approach I have taken as I have moved some of the elements out of the timeline. It all works 😀 but I also feel like I may have made a few more mistakes. So would welcome any more advice. Also please let me know if this belongs in a new thread instead.

 

I moved the fixed image to within the CSS so got around the need to make it fixed later. I've then added some animation to the text and the images in the following sections.

 

At first I added all of this to the timeline, but I struggled to get the timing right, and it felt wrong to create selectors for each of the elements I wanted to animate. I don't know if multiple timelines are considered bad practice?

 

Looking at the .batch() demos and also the

See the Pen wvMeNee by GreenSock (@GreenSock) on CodePen

 they seemed like a good approach to take.

 

At first I thought that .batch() could work but I was not able to select the individual element, (I'm trying to get two of the images to overlap as the page is scrolled). I've been able to do this in the codepen below by using an array of the items instead.

 

I feek like I may have made some mistakes again as I've found I needed to remove the pinSpacing from the timeline or the spacing for the following scrollTriggers appears out of place. (I'm ok with this as I need to try and get the subsequent text/image animations overlapping with the mask slightly)

 

See the Pen MWJOoNz?editors=1010 by Seanom (@Seanom) on CodePen

 

 

I toyed with using the following approach, but I'm not sure this is the correct approach as I want to trigger the moment with each image, not the position within the container. 

const image1 = document.querySelector('.o-image-1');
const image2 = document.querySelector('.o-image-2');
const image3 = document.querySelector('.o-image-3');

var tl2 = gsap.timeline({
         scrollTrigger: {
             trigger: '.--fixed',
             start: "top center",
             end: "15px bottom",
         },
         defaults: {
             duration: 4,
             ease: "power3"
         }
     }).to(image1, {
        yPercent: 25,
     }, 0)
         .to(image2, {
             yPercent: -25,
     }, 0)
         .to(image3, {
             yPercent: -12,
     }, 1)
 ;

 

Link to comment
Share on other sites

 

Hey seanom.

 

I can't take a detailed look on everything and review your code like that, but if it works the way you wanted and you don't get any errors in your console, that is a good sign :) 

 

 

14 minutes ago, seanom said:

I feek like I may have made some mistakes again as I've found I needed to remove the pinSpacing from the timeline or the spacing for the following scrollTriggers appears out of place.

 

That might be related to creating your ScrollTriggers out of order of appearance on the page. From a quick glimpse, it looks like in your JS you seem to be creating the ScrollTriggers for the images before the pinning ScrollTrigger for the mask - so those first created ScrollTriggers have no knowledge of the pinSpacing applied by the pinning ScrollTrigger - which maybe threw things off for you timingwise. It's best to create the your ScrollTriggers in order of appearance on your page.

 

 

16 minutes ago, seanom said:

(I'm ok with this as I need to try and get the subsequent text/image animations overlapping with the mask slightly)

 

But since you want your text and images scrolling in to overlap with the mak-animation anyway, I think pinSpacing: false would have been the tool of choice anyways.

 

If in some case you don't have any chance do do that (like when handling multiple items throughout the page in a forEach-loop e.g. that are devided by a pinning ScrollTrigger) there is the very hand ScrollTrigger.sort()-method that can help.

 

 

19 minutes ago, seanom said:

I don't know if multiple timelines are considered bad practice?

 

I don't think that would be considered bad practice. Oftentimes there are various different ways of how to approach things, and splitting things up into different timelines can often be very convenient to get the timing right - as you mentioned. So I guess in a way and depending on the usecase - with regard to redability of your code for example -  it could even be considered good practice.

 

 

Good job so far :) (maybe somebody else with a bit more time at hand sees something that i missed though)

 

 

  • Thanks 1
Link to comment
Share on other sites

  • 1 year later...

Hi guys. 

This is super cool. But does anyone know if this is possible to implement this functionality via plain css/js?

 

I am trying to have a borders of a certain county as my starting image. Then, when scrolling down, this country starts zooming out further and further until it transform into a picture of the entire world map. Basically, seanom's original post, but a circle has borders of a specific country. And written in  html/css/js?

 

Thank you. 

Link to comment
Share on other sites

Just wanted to mention that while the demos posted by me are set to SCSS, Blake's original in there doesn't even use any SCSS syntax and my forks of that one only really use SCSS for commenting things out like //this instead of /* this */ - Sorry for any confusion, it's just a habit of mine!

 

The only demo making use of Pug looks to be the original one by the OP - but since that one is not functioning as intended to begin with, maybe it wouldn't be the best idea to take that one as a starting point.

Link to comment
Share on other sites

31 minutes ago, akapowl said:

SCSS syntax and my forks of that one only really use SCSS for commenting things out like //this instead of /* this */ - Sorry for any confusion, it's just a habit of mine!

 

Ha, that's basically the only reason I have my pens set to use SCSS. 

  • Haha 1
Link to comment
Share on other sites

I definitely know about the shortcut. The thing I like is to be able to comment out more than 1 line at time, but then later uncomment an individual line.

 

To uncomment display: flex would require uncommenting everything. You don't have this issue with SCSS.

 

section.spacer {
/*   height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center; */
}

 

  • Like 1
Link to comment
Share on other sites

ahhh... that makes perfect sense. 

 

I just never want to assume something simple is common knowledge. I had an employee once who was typing out the <!-- --> around his HTML. He nearly fainted when I showed him the shortcut. 

 

Link to comment
Share on other sites

9 hours ago, PointC said:

I've always used the ALT drag through the lines for individual line comments on the CSS.

 

You can do it like that - but if you have just one or two lines commented out like that and then decide to comment out the whole block (to e.g. try a whole different approach but still keep the previous one in your code as backup), that won't work.

 

css.gif.1e621f37d0c27b35e54f400ad5f72a50.gif

 

 

 

The SCSS syntax also allows 'nesting' comments.

 

scss.gif.bfabe117c5161e24865605d7c2f5328a.gif

 

  • Like 3
Link to comment
Share on other sites

  • 9 months later...
On 3/26/2021 at 12:03 PM, akapowl said:

 

 

Hello @seanom

 

Using a timeline certainly is the best way to approach this - but with your approach you are actually making one of the most common ScrollTrigger mistakes; nesting ScrollTriggers inside multiple timeline-tweens. You'd want to avoid that and instead set up the scrollTrigger on the timeline itself.

 

 

You can use the position parameter of the timeline (more info on that right below the video on the linked docs-page) to properly adjust the timing for the individual tweens of yout timeline. But be aware, that durations and the position parameter on ScrollTrigger-tweens and -timelines with a scrub applied do work quite different from those on regular tweens/timelines.

 

 

 

As for the mask-reveal:

@OSUblake made an awesome demo that shows how such a cirlce mask-reveal can be achieved - responsive to resizes and everything included.

 

 

 

 

 

I went ahead and adjusted it a bit so it fits the scenario you described - so you could take this as inspiration for how to achieve your goal.

For the image to remain in place on further scrolling ( in this special scenario ) I found it would be easiest to just have it positioned fixed outside of any section and hidden initially and then simply tween its opacity to 1 when the time has come. Depending on the exact outcome you want for this later on scrolling it might be better to do things differently though.

 

 

 

 

 

Hope this was a bit helpful. Happy tinkering, scrolling and tweening :) 

 

 

Edit:

Because of the image being positioned fixed in the above approach this would of course not work with the image being initially visible through that hole in the black section, so here is a different approach with one image fixed and one absolute inside the section and a switch of opacity between those at the end of the scrubbing timeline ( will lead to a nasty jump with a numerical scrub-value though so the scrub is set to true ). Maybe somebody else has a simpler approach to that.

 

 

 

 

 

Hi, great job on this image reveal sample.  Would someone be willing to show this reveal with a rectangular reveal shape, versus the circle shape?

Link to comment
Share on other sites

3 hours ago, rm2773 said:

Would someone be willing to show this reveal with a rectangular reveal shape, versus the circle shape

I think for this, and the current browser support, I'd probably try to animate clip-path:

Start with something like: clip-path: inset(40%);

 

Then gsap.to('.el', { clipPath: 'inset(0%)' }

 

See the Pen mdGymXP by elegantseagulls (@elegantseagulls) on CodePen

 

  • Like 2
Link to comment
Share on other sites

On 2/15/2023 at 1:38 PM, elegantseagulls said:

I think for this, and the current browser support, I'd probably try to animate clip-path:

Start with something like: clip-path: inset(40%);

 

Then gsap.to('.el', { clipPath: 'inset(0%)' }

 

 

 

 

Thanks for posting this solution - much appreciated!

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