Jump to content
Search Community

ScrollTrigger - Triggering animations horizontally

tonysandwich test
Moderator Tag

Recommended Posts

I have a section in a page scrolling horizontally and I have created an image parallax within this, however it is currently being triggered by a vertical position. 

 

This is ok for the first panel but I have two panels that I would like to parallax (.horizontal-test) but they are both animating at the same time so by the time the second panel enters the screen the parallax animation has already taken place.

 

Is there any way to trigger an animation based on the horizontal position of a div when scrolling horizontally?

 

Thanks!

See the Pen 68f0498debc85352c4f86ecaa57425e0 by EightArmsHQ (@EightArmsHQ) on CodePen

Link to comment
Share on other sites

Hey Tony and welcome to the GreenSock forums.

 

The reason your demo works the way that it does is because both of your elements start at the top of the page and, since that's your start position, both start at the very beginning scroll. Then they both end when the image's height has been scrolled to. 

 

What you want to do instead is use their left and right positions. But since you're not actually using true horizontal scrolling you can't just use horizontal: true. Instead you need to calculate their offsets yourself. However you might even need different calculations for your images because your last one is the last part of the pinned section so technically if you want the same parallax distance before the pin ends it'd have to go faster. Does that make sense?

 

I didn't compensate for that in the code below but I think you should get the jist of what I mean:

gsap.utils.toArray('.horizontal-test').forEach((horizontalPanel, i) =>{
  gsap.to(horizontalPanel, {
    x: "-10%",
    scrollTrigger: {
      // Essentially the same as "top bottom"
      start: horizontalPanel.offsetLeft,
      // Essentially the same as "bottom top"
      end: horizontalPanel.offsetLeft + horizontalPanel.offsetWidth + innerWidth,
      scrub: 0.5,
      markers: true
    }
  });
});

 

Link to comment
Share on other sites

Hey Zach, 

 

Thanks so much for that, I had a feeling it would have something to do with the offset. 

It's definitely got me heading in the right direction, and thanks for the heads up on the last image.

 

The issue that I"m still having however is that all the .horizontal-test divs are all starting to transform at the same time as soon as the page is scrolled, rather than each one starting as it appears in the viewport, any ideas why this may be?

263229740_Screenshot2020-08-20at14_58_01.thumb.png.85acd0776c47a266e204134597cd1742.png

 

Updated pen here:

See the Pen 685524faa6aa0bd628d659103be5d585 by EightArmsHQ (@EightArmsHQ) on CodePen

 

thanks again.

Link to comment
Share on other sites

Sorry, I didn't check your markup too closely - offset only gets the offset from the parent, which I mistakenly assumed would work in your case. And my calculations were wrong, hah. I guess I hadn't woken up yet ;) 

 

Since the element you're selecting is nested you should use either the parent's offset or the element's .getBoundingClientRect() depending on the exact effect that you want. To be more consistent regardless of the image size you should probably use  the parent's offset.

 

I also realized that your end value for the first ScrollTrigger was incorrect so I fixed that:

let container = document.getElementById("horizontal-wrap");

gsap.to(container, {
  x: () => -(container.scrollWidth - document.documentElement.clientWidth),
  ease: "none",
  scrollTrigger: {
    trigger: container,
    invalidateOnRefresh: true,
    pin: true,
    scrub: 0.5,
    start: "top top",
    end: () => "+=" + (container.scrollWidth - document.documentElement.clientWidth)
  }
})

gsap.utils.toArray('.horizontal-test').forEach((horizontalPanel, i) => {
  const parent = horizontalPanel.parentElement;
  gsap.to(horizontalPanel, {
    xPercent: 30,
    ease: "none",
    scrollTrigger: {
      start: parent.offsetLeft - innerWidth,
      end: parent.offsetLeft + parent.offsetWidth,
      scrub: 0.5,
      markers: true
    }
  });
});

 

  • Like 1
Link to comment
Share on other sites

Hey Zach, just got one small issue.

I am not starting the horizontal scroll until further down the page, however the parallaxing on the images is starting as soon as the page scrolls, updated pen here:

 

See the Pen 685524faa6aa0bd628d659103be5d585 by EightArmsHQ (@EightArmsHQ) on CodePen



I tried using a trigger for the top of the carousel but that didn't seem to work. Any ideas? 

Thanks.

Link to comment
Share on other sites

Since the value is calculated you need to modify the calculation. Add the y offset of the container:

const container = document.getElementById("horizontal-wrap");
const topContainer = document.querySelector('.test');

gsap.to(container, {
  x: () => -(container.scrollWidth - document.documentElement.clientWidth),
  ease: "none",
  scrollTrigger: {
    trigger: container,
    invalidateOnRefresh: true,
    pin: true,
    scrub: 0.5,
    start: "top top",
    end: () => "+=" + (container.scrollWidth - document.documentElement.clientWidth)
  }
})

gsap.utils.toArray('.horizontal-test').forEach((horizontalPanel, i) => {
  const parent = horizontalPanel.parentElement;
  gsap.to(horizontalPanel, {
    xPercent: 30,
    ease: "none",
    scrollTrigger: {
      start: topContainer.offsetTop + parent.offsetLeft - innerWidth,
      end: topContainer.offsetTop + parent.offsetLeft + parent.offsetWidth,
      scrub: 0.5,
      markers: true
    }
  });
});

 

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