Jump to content
Search Community

ScrollTrigger 3d carousel like twitch.tv

jacobiwan test
Moderator Tag

Recommended Posts

I've spent the last couple weeks researching here and there about how to implement a 3d carousel, similar to the one you see on Twitch. Though the difference being that it would be vertical and it would activate on scroll, not on clicking the left/right (up/down) arrows. Similarish to this

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

that I found in the forums here, though not draggable.

 

I added a codepen that I threw together really quickly of the outline I have so far. Tomorrow morning when I get some more time I will adjust it to be a bit more accurate. Anyways, my question is, has anyone seen something like that implemented that I could get ideas from? If so or not, do you believe it would be easy enough or should I rethink the design?

 

Any feedback is appreciated!

See the Pen PoGgzaP by jakeatunova (@jakeatunova) on CodePen

Link to comment
Share on other sites

Hey jacobiwan. The hard part about infinite things on scroll is that the scroll bar is limited while the effect that you're wanting is not. So you have to either loop the scroll position like this demo (found in the ScrollTrigger demos section) or hook directly into the scroll-related navigation events (like the wheel event) instead of actually using the actual scroll position. The actual slider animation and wrapping part is fairly easy and there are a lot of examples that you can find in these forums of infinite sliders/carousels. 

  • Like 2
Link to comment
Share on other sites

Hey Zach!

 

Thanks for that info. I didn't even realize this in the examples I sent, but honestly infinite scroll isn't even a concern to me. In my example, the carousel starts on the middle element and scrolls either way. If it hits either the first or the last element, it's okay if it stops scrolling and you have to scroll the other way. Infinite scroll is definitely something I want to look into now, but it's not necessary for now and I can look into it after I get an MVP going.

 

For now, I think that draggable years example is the closest thing to what would work for me. It can be a simple effect and doesn't need to be a 3D carousel exactly. The minimal features I need from it are:

  1. Scroll through the elements
  2. One element always in focus

Some nice features would be:

  1. Coming into focus is animated
  2. Infinite scroll
  3. 3D carousel

With these guidelines, it could be a pure vertical scroll where it snaps to the element in the middle of the viewport (I'm sure that's been done before, have you seen it on the forum here? Didn't have any luck with my searches). And then I can expand on it from there. I'll look a bit deeper into the codepen above with the years. My current setup is a fixed vertically scrollable element that pops in from the right side when opened. I'm trying to figure out how to set the scrolltrigger relevant to the fixed element and not the body. Ultimately it will be to display different types of media, videos/clips, iframes.

Link to comment
Share on other sites

Hey @ZachSaucier! I've created the animation. Wondering if you can guide me towards attaching it to a ScrollTrigger? Here is what I have so far: 

See the Pen yLaWwmX by jakeatunova (@jakeatunova) on CodePen

 

It's simple. Ultimately I'd like to add a bit more to the animation, but that's about as minimal as it needs to be. I've created a few scrolltriggers, but just simple things like pinning something to the top as you pass it. One thing in particular I'm unsure about with this one is that the #content-channels div is going to be fixed position off the right side of the screen and on click of a button it slides in. When I've attempted to add a scroll trigger and show markers, it's as if it's attached to the body, instead of the .media-frames box. Also, any general info you have on just hooking timelines to scrolltriggers would be helpful. Going to do some research this weekend on that!

 

Thanks!

Link to comment
Share on other sites

First things first: in order to have some sort of scrolling animation you have to have some scrolling.  You should also be loading ScrollTrigger :) 

 

It's not clear what effect exactly you're going for (should the inner section scroll? Or the outer container?). I just made #content-channels the scroller, added an empty element to size the scroll section (since your content is absolutely positioned), put the other content in a container (so it's easier to pin) and then set up the ScrollTrigger like so.

See the Pen GRjbGaQ?editors=0110 by GreenSock (@GreenSock) on CodePen

 

I highly recommend going through the ScrollTrigger docs :) 

 

Side note: I removed your > selectors because it messes up the styling since pinning has to add a container element around your content. In general you should avoid using > unless you need to use it because if the markup changes it makes your CSS harder to maintain. The same goes for nesting selectors (i.e. using child selectors) but I didn't remove those. 

  • Like 2
Link to comment
Share on other sites

Wow @ZachSaucier! Thanks so much for your help and feedback. I apologize, I didn't mean for you to do it all for me. This is almost exactly what I was looking for.

 

The way I've created ScrollTriggers so far is using ScrollTrigger.create(). I only recently realized you could pass a scrollTrigger object to a timeline and hadn't quite understood it yet, but your example is pretty clear. I plan to read all the docs here pretty soon, which I am now, but slowly, and do some practice projects.

 

That's good to know on the immediate child selectors! I think that this would be the first situation that it would mess me up in as I don't usually use many other libraries that change my html and since I'm just building simple websites for the most part, it's not difficult to change something when I need to. But I will keep it in mind going forward and try to avoid them.

 

Thanks again!

Link to comment
Share on other sites

14 minutes ago, jacobiwan said:

I don't usually use many other libraries that change my html and since I'm just building simple websites for the most part, it's not difficult to change something when I need to.

It's not just libraries that cause changes in DOM structure - it can also be restructuring your page. Or including a component in multiple parts of a page. There are a lot of different viewpoints on how to structure CSS, but always using nested selectors is almost always frowned upon in larger projects or team settings :) 

Link to comment
Share on other sites

That's a good point! I guess I just haven't come across that yet. I'll work on refactoring it properly. Thanks for all your help btw. I'm pretty close to finishing up. Just looking into snapping and running some code when a frame is centered! When I've finished up I'll put the updated codepen here.

Link to comment
Share on other sites

  • 2 weeks later...

Hey @ZachSaucier,

 

I've been working on this here and there and I'm wondering, is it considered scrolljacking if instead of a smooth scroll like in this Codepen 

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

 It's a step scroll. As in, one scroll moves the position of each frame up/down one. This is with the idea being that there is always one frame perfectly centered.

Link to comment
Share on other sites

To finish what I was saying. The ideal situation is where a frame is always in each position. Meaning that on scroll, it snaps to the positions. Though this might mean that it would involve scrolljacking?

 

Anyways, my work-around for now (which I'll provide a codepen for when I'm finished) is instead of animating each frame through the timeline and staggering them, I animate the entire stack of frames one position, then another, then another. I'm still working out what the best way to write that code looks like, but I think it will suit my needs a lot better than the initial way I thought it out.

Link to comment
Share on other sites

12 minutes ago, jacobiwan said:

on scroll, it snaps to the positions. Though this might mean that it would involve scrolljacking?

It depends on the implementation. Any time that you replace the built in scroll functionality, it's considered scrolljacking. 

 

However you can do snapping with ScrollTrigger which doesn't do scrolljacking. Essentially snapping with ScrollTrigger notes when a user is done scrolling then adjusts the scroll position to the closest snap point.

 

The demo above with ScrollTrigger's snapping added:

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

Link to comment
Share on other sites

That makes a lot of sense Zach!

 

Since working with GSAP over the last month or two, I've started just creating all my animations in codepen first in case I need to share haha.

 

I've updated what I had originally based off your help with the scroll triggers to this codepen 

See the Pen ZEBQewN by jakeatunova (@jakeatunova) on CodePen

 

To me, this animation makes more sense. Instead of creating timelines for each frame to animate through all positions and staggering them, I've created timelines for shifts in the carousel where each frame shifts into the adjacent position. And I've done a bit of refactoring (took me a bit of time to figure out how to loop over this to keep things tidy, I'm sure I have some more refactoring I could do). So I'm left with a few questions:

 

  1. On mobile this is suuper stuttery. Scrolling on it feels like it has the screen shake animation attached, but not in a good way. Is that just an issue with mobile browsers or is there something in my implementation causing that? I was experiencing the same issue with the previous codepen.
  2. I'm curious about the CSSRulePlugin. One problem I think it will solve for me is that when I load the content channels on my site, a few frames load in immediately while others are added after a response from an ajax call. This makes me have to rebuild the timeline when I get the response back from that call because if I don't, the new frames will not be positioned properly. My poor (so far) understanding of CSSRule is that might solve that by using the css style sheets instead of the dom attributes, is that correct?
  3. Following up on that, I'm researching this now, but when I replace element with a CSSRulePlugin.getRule(`.media-frame-desktop:nth-child(n)`) and then attach it to an animation, I get an error saying that the element is undefined. I've registered the plugin and I've added the cssRule property to the animation properties object (`positions` in my code). Not quite sure what that would be and haven't been able to find anything so far.

Thanks again for all your help! It's turning out just how I pictured it and I think I'm wrapping my head around scroll triggers and basic animations so far.

Link to comment
Share on other sites

11 hours ago, jacobiwan said:

is there something in my implementation causing that?

The biggest things I notice that you could do to improve performance based on your code are:

  1. Animating top and left is definitely bad for performance. Stick to animating x and y instead.
  2. Use will-change: transform, opacity.

About CSSRulePlugin: We don't really recommend CSSRulePlugin. It's not as performant or as capable as regular tweens. 

 

In your situation if you know how much content will be loaded you could set up "empty" elements that are setup and then when the content loads you add it to the relevant empty element. If you don't know how many will be added, I still don't think you need to recreate your timeline again but it's unclear as the logic inside of your for loops is not straightforward to me. 

 

Side notes:

  • Why use a function to return a selector string with the given index? It'd be better to keep an array of the elements and then just do myElemArray[i]...
  • I'm not sure why you're using a timeline to set the initial positions. 
  • Instead of looping through an array of elements and setting them to the exact same thing, just set them with one .set() call:
    gsap.set(offsetFrameStack, positions[0])

     

Link to comment
Share on other sites

Wow, I would've thought that top/left/right/bottom were performant to animate. Makes sense why not though. I also didn't know about that will-change property.

 

Unfortunately, I don't know how many will be added, but that's not a large concern. I can work around that. I was getting some additional space at the end of the scroll that would push the frames up and off center. Adding `ScrollTrigger.refresh()` after the additional frames load in mostly fixes that issue.


Also, thanks for your side notes 🙂. A few of those things were left over from the way I was doing things before when I was just focused on getting it to work and I hadn't realized or revisited them.

 

I'm still working out some kinks, but one that I can't figure out is why the top 3 animations don't animate and simply jump. Looking through the docs and forums I don't see any similar issues.

 

Link to comment
Share on other sites

18 minutes ago, jacobiwan said:

why the top 3 animations don't animate and simply jump

That's a logical issue based on how you're creating the tweens in the timeline. It might help you understand what's going on if you stripped out all of the parts not directly related to the animation and then parts of the timeline itself to see what's happening exactly.

Link to comment
Share on other sites

  • 3 weeks later...

Hey Zach! Appreciate all your help on this! I made the changes that we talked about. I keep revisiting this part of the site if I've been struggling with it for too long to make sure I get other things done too.

 

I figured out why the top 3 animations don't animate and it's actually causing more issues that I'm trying to understand. It happens when I use `gsap.set` to set the positions of the first 3 frames. After that I set the position of the remaining frames offscreen. However, if I set them all to start offscreen with just one `gsap.set` instead of 4, then the animation works flawlessly (aside from the starting state being incorrect). Looking at the docs for `gsap.set` I don't see anything that hints at why this would be a side effect of setting the initial positions this way.

 

Here is the codepen. I've taken out a few frames for simplicity and removed any loops in favor of writing out each timeline manually to make sure that the animations were being set up correctly. Right now I'm toying with the css to see if it's the initial styling that's messing things up. Right now I have all frames styled to the center right of the screen, then they get set with gsap to off screen on the top right.

 

See the Pen ZEBQewN by jakeatunova (@jakeatunova) on CodePen

Link to comment
Share on other sites

@ZachSaucier That makes a lot of sense the way you're doing it. Originally, I attempted to do something similar, but animating each frame all the way through before animating the next frame proved to be more difficult to me to line up properly than the way I've had it lately. But what you have here seems to work just fine, so thank you for that and for all your help.

 

@Shrug ¯\_(ツ)_/¯ Before starting on this, I tried to search google, the forums and portfolios for something just like that! I found pretty much next to nothing and particularly someone saying that building an infinite scroll would be pretty complicated, so I just tossed the idea out. But yes, that's exactly what I'm looking to do, just vertically. I'll look into that more as part of a v2. Thanks a lot!

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