Jump to content
Search Community

Horizontal Image Slider for panorama image and multiple images

hightwo test
Moderator Tag

Go to solution Solved by akapowl,

Recommended Posts

Hey there!

 

I would like to improve stories on our blog with more+animated images (sort of scrollytelling). So I came across Scrolltrigger and tried to create two types of horizontal image sliders:
 

  • One for multiple images (landscape and portrait mixed) and
  • one for a single pano image.

 

I only have basic JS knowledge (but I am working on it ;-) and I'm currently struggling with the following issues:

 

  • multiple images (first section in the pen):
    I managed to calculate the scoll-width by summing up the objectWidth of each img. Depending on the browser and image filesize I had problems to get a correct objectWidth. So I tried window.onload, but this left me confused on how to arrange it with the Tween. Above all this is of course not recalculated when the window is resized.

    What is a good way to make this responsive?
    Like animating some sort of objectPosition 0 to 100% (see next section below)?

     
  • single pano image (second section):
    The single pano is placed into the div using object-fit. Then I was able to animate objectPosition from 0% to 100%.

    What is the recommended way to calculate the end of the Scrolltrigger to make the "scroll duration" responsive?
    Like scroll-width of the pano minus viewport-with?

     
  • Overflow: hidden
    Currently I try to set overflow-x: hidden on the body.

    Is there a better way to handle this?

 

Hope I could explain it clearly. Thanks for your help!

 

Andreas

 

See the Pen YzpwowJ by hightwo (@hightwo) on CodePen

Link to comment
Share on other sites

  • Solution

Hey @hightwo

 

On the ScrollTrigger demos-page there is a demo which showcases one version of a horizontal fake-scroll that comes very close to what you are attempting.

 

You could take that as a refference for how to make it responsive (just think of the sections in that example as your images).

The key for that is the use of function-based values for your start/end and the values you are tweening on; like so for example (note the arrow function):

 

end: () => `+=${maxWidth}`,

 

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

 

 

As for the overflow-x: hidden:

You put that exactly where it is supposed to be - your body 👍

 

Hope this helps. And welcome to the forums :) 

Cheers.

 

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

Many thanks @akapowl!

 

Somehow I have missed this demo yet, sorry.

I updated my slider with the eventListener and the function to calculate the max/totalWidth in this fork 

See the Pen JjbXyjw by hightwo (@hightwo) on CodePen

 

... and it works fine 👍

... and even better: Seems I can use the same animation for the single-pano-slider as well! So no need for a second type of slider (animating the objectPosition).

 

However I need to dig a bit deeper into the syntax of the function based end-value, arrow functions etc. to fully comprehend it 🤓.

Nevertheless it's nice to see, that my basic approach wasn't completely wrong :-) and the logic is clear.

 

Now just need to get this work for multiple sliders on one page. Hope I will manage it with a forEach.

 

A question on this:

Is the eventListener still the preferred way if I have e.g. five of the sliders on one page?

Or may I run into some performance issues since the max/totalWidth function will be executed for each slider on each resize?

 

Thanks!

Link to comment
Share on other sites

On 2/6/2021 at 11:34 PM, hightwo said:

By the way: I discovered that overflow-x: hidden in the body still let me scroll horizontally prior to the slider.

 

Interesting. For me it doesn't 🤔

 

 

On 2/6/2021 at 11:31 PM, hightwo said:

 

However I need to dig a bit deeper into the syntax of the function based end-value, arrow functions etc. to fully comprehend it 🤓.

 

One small piece of advice: you might want to consider changing the ease on the tween to 'none' depending on how you want things to happen, because by default GSAP adds a power1.out (you can notice that in your example the 'horizontal scrolling' becomes slower towards the end).

 

 

On 2/6/2021 at 11:31 PM, hightwo said:

Is the eventListener still the preferred way if I have e.g. five of the sliders on one page?

Or may I run into some performance issues since the max/totalWidth function will be executed for each slider on each resize?

 

Since the eventListener is set to the ScrollTrigger's refreshInit and not every resize of the brower, performance is pretty much considered for this, since ScrollTrigger's events are debounced on resize and won't fire on every resize event. I don't think that should be an issue - but maybe I am also not the best person to answer this.

 

 

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

Hi @akapowl,

 

thanks for the follow-up. Meanwhile I played around a with the code in VS Code and different browsers... mainly figuring out how to use this code for more than one horizontal slider per page... any hint appreciated ;-) I didn't find a good starting point yet.

 

And I discovered some other issues:

 

On 2/8/2021 at 10:32 AM, akapowl said:
On 2/6/2021 at 11:34 PM, hightwo said:

By the way: I discovered that overflow-x: hidden in the body still let me scroll horizontally prior to the slider.

 

Interesting. For me it doesn't 🤔

I just figured out, that overflow-x: hiddenin the body works as expected in Firefox and Chrome, but not in Safari.

 

On 2/8/2021 at 10:32 AM, akapowl said:

you might want to consider changing the ease

Thanks for the hint. Eases are clear so far.

By the way: cool thing that possibilities for the eases are almost limitless in GSAP.

 

On 2/8/2021 at 10:32 AM, akapowl said:

is set to the ScrollTrigger's refreshInit and not every resize of the brower

What I found out when running this piece in VS Code (outside codepen):

 

Resizes in horizontal direction are handled as expected, but not, when I resize the browser in it's height (vertically).

Reducing the height leaves some white space right of the images (of course, they are getting smaller)

 

If I then resize it horizontally, it is calculated correctly again.

Link to comment
Share on other sites

15 hours ago, hightwo said:

Resizes in horizontal direction are handled as expected, but not, when I resize the browser in it's height (vertically).

Reducing the height leaves some white space right of the images (of course, they are getting smaller)

 

You can also see this behaviour when using codepen's debug view.

I looked at this for quite a  while now, and I can not seem to find an explanation or workaround for this, sorry.

 

Maybe @GreenSock or @ZachSaucier could have a look at this?

 

 

 

Also, maybe this altenative approach of tweening on the container itself instead of each individual image could be sufficient for you - at least it doesn't show the issue. I wrapped it in a .forEach-function to show how you can apply it to multiple sections. What you might want to consider if you later on create ScrollTriggers that are supposed to trigger in between those sections, is to use a refreshPriority or a .sort() after creating all your ScrollTriggers because you won't be able to create them in the order they appear on the page and that will throw ScrollTrigger's calculations off due to the pinning.

 

See the Pen 758883b269fb198db8e882bba7aef2bc by akapowl (@akapowl) on CodePen

 

 

  • Like 1
Link to comment
Share on other sites

Thanks @akapowl for the alternative approach. If it works in the end I don't care what to tween :-)

Many thanks for your advice on "forEach-ing" the whole thing.

 

Just tested the pen in Chrome, Firefox and Safari. Seems to work as expected 👍

(apart from overflow-x: hidden on the body... somehow Safari behaves different here 🤔)

 

What I am wondering: Does this work now without the resfreshInit eventListener that we had in the first example?

ScrollTrigger.addEventListener('refreshInit', getTotalWidth);

 

 I will try it it my project and test it in the next days.

Link to comment
Share on other sites

3 hours ago, hightwo said:

What I am wondering: Does this work now without the resfreshInit eventListener that we had in the first example?

 

Yes, because here it is being tweened to the left on the x-axis dependent on the scrollWidth of the container - so there is no need to calculate the width beforehand - we can just get it. This also does not mean, you would have to animate the container instead of the images - you could also tween every image individually dependent on that as before (you'd just have to make sure you only address the images in that container if you were to apply it for multiple sections).

 

In some scenarios one might be more helpful than the other.

If you don't want to do anything else but move the images to the left, I would go for whatever feels most comprehensible to you.

 

  • Thanks 1
Link to comment
Share on other sites

I think the problem is that you were measuring the widths in a "refreshInit" event which fires BEFORE the page is reverted to its natural state, meaning that the pinSpacer is still in the page propping things open. So that throws your measurements off. Instead, you should use the "revert" event which fires inbetween the "refreshInit" and "refresh" events, when the page has been reverted to its natural state (pinning spacers removed): 

See the Pen 12be1421c36f3c81f3b8b695730f97c5?editors=0010 by GreenSock (@GreenSock) on CodePen

 

Another problems was this: 

`-${totalWidth - document.documentElement.clientWidth}`

If that results in a negative number, you'll end up with a string like "--25" which doesn't make much sense. 

 

Does that clear things up? 

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

Many thanks @GreenSock for optimizing the initial idea. I updated your advice to my project and it works as expected 👍.

I also tried @akapowls suggestion of tweening the container itself using scrollWidth. Works well too 🤘.

 

So for this issue I really thank you guys providing not just one solution, but two :-) 

I will continue with tweening the container as this seems a little simpler and does the job.

 

Anyway checking both solutions definitely improved my understanding of GSAP and how to combine it with different values and functions.

You may consider it as solved and I'll be happy to bother you with more GSAP questions in the future as my project continues.

 

Thanks!

 

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