Jump to content
Search Community

Give me your cleanest, leanest carousels...

monospace test
Moderator Tag

Go to solution Solved by GreenSock,

Recommended Posts

Apologies for starting yet another "carousel" related topic, but I was hoping some of the brilliant minds here could help me out. 

Is there a way to use GSAP to create an infinite looping "carousel" style animation that doesn't repeat the first element in the list, like this embedded CodePen? Mind you: I'm not looking for fancy controls to start or stop or reverse anything, just a simple, clean way to loop a bunch of items that also makes sense in a screen reader type of environment—no repetitions of items in the source code.

 

See the Pen LYLOdPa by monospace (@monospace) on CodePen

Link to comment
Share on other sites

Are you saying that the very first element should be part of the first iteration/loop, but then you never see that one element again (but you do see all the others in a never-ending loop)? 

 

Also, when you say "cleanest, leanest carousels" do you mean "smallest amount of code (even if it requires 30% more CPU)" or "most performant"? I always lean toward solutions that perform better even if it requires 50% more code, but if you just want the smallest amount of code that's important to know. 

Link to comment
Share on other sites

  • Solution

After re-reading your question and looking at your demo, I think I understand what you mean - you're trying to avoid the DUPLICATE first element. You just want a normal group of elements that infinitely loop seamlessly. 

 

I've got two ways you could approach this - one uses less code but is more CPU-intensive because it has to modify each value on every tick: 

let height = 50,
    boxes = gsap.utils.toArray(".box");
boxes.forEach((el, i) => {
  gsap.to(el, {
    y: boxes.length * -height,
    modifiers: {
      y: gsap.utils.unitize(gsap.utils.wrap((i + 1) * -height, (boxes.length - i - 1) * height), "px")
    },
    duration: 2,
    repeat: -1,
    ease: "none"
  });
});

 

And here's a more performant version that uses a bit more code: 

let height = 50,
    boxes = gsap.utils.toArray(".box"),
    duration = 2,
    tl = gsap.timeline({repeat: -1, defaults: {ease: "none"}});
boxes.forEach((el, i) => {
  let dur = duration / boxes.length * (i + 1);
  tl.to(el, {
    y: -height * (i + 1),
    duration: dur
  }, 0).fromTo(el, {y: height * (boxes.length - i - 1)}, {
    y: 0,
    duration: duration - dur,
    immediateRender: false
  }, ">");
});

 

Here are both in a CodePen:

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

 

Is that what you're looking for? 

  • Like 5
Link to comment
Share on other sites

I'm currently in the process of building a slider of sorts using GSAP. It animates between two 'slides', so it never loops, because it is always an animation between two elements. This also allows me too animate between the first and the last item if desired.

 

See the Pen YzQZBgr by mvaneijgen (@mvaneijgen) on CodePen

 

This is more a slider and it will wait ever X amount of seconds before sliding to the next slide, but this can of course be decreased.

 

My example has a really 'fancy' animation, but this is just to show what is possible thanks to GSAP. I wanted to build it this way so I could easily swap out the animation to be like in your example vertically, so if you want you can easily change the code to your liking.

 

This is my first (working version) and I'm not sure if I would use this in production already, but it works and it does what I want.

 

Edit: Did some tweaking to see if my code could adapt to create something like your demo and it was indeed possible 

See the Pen OJgzPbQ?editors=0010 by mvaneijgen (@mvaneijgen) on CodePen

  • Like 6
Link to comment
Share on other sites

12 hours ago, GreenSock said:

Are you saying that the very first element should be part of the first iteration/loop, but then you never see that one element again (but you do see all the others in a never-ending loop)? 

 

Also, when you say "cleanest, leanest carousels" do you mean "smallest amount of code (even if it requires 30% more CPU)" or "most performant"? I always lean toward solutions that perform better even if it requires 50% more code, but if you just want the smallest amount of code that's important to know. 

 

I want to avoid duplicating the first or the last item, because that would mess with screen readers. I would also like to avoid having to do any specific prep work on the items themselves, that is, I want to be able to use them as provided (be they images, divs, whatever) without having to modify them in any way.

And by lean and clean I mean code that has the least amount of bells and whistles (no sliders, pause or reverse buttons, etc), and is easy to comprehend and modify (i.e. change x-axis to y-axis, maybe add a fade or a scale or a bounce or something.) Ideally of course it wouldn't bring down a user's computer, but I don't think that's much of an issue in this day and age. I don't mind a few extra lines of code to accomplish that. 

All that said, thanks for those very interesting examples. I'm going to have to spend some time tinkering with those.

Link to comment
Share on other sites

17 minutes ago, monospace said:

I want to avoid duplicating the first or the last item, because that would mess with screen readers. I would also like to avoid having to do any specific prep work on the items themselves, that is, I want to be able to use them as provided (be they images, divs, whatever) without having to modify them in any way.

The solutions I provided accomplish this. However, they depend on all the elements being a specific height and lining up edge-to-edge. Of course it's entirely possible to edit them to accommodate variable heights and positions but that will inevitably make the code more complex. That's one of the reasons why I put the helper function together here: 

https://greensock.com/docs/v3/HelperFunctions#loop

 

It solves a bunch of problems that people tend to run into. And of course that requires more code/complexity. 

 

Hopefully we've given you plenty to work with that will allow you to land on a solution that's simplistic enough for your needs without going overboard with features. 

 

Good luck!

  • Like 2
Link to comment
Share on other sites

Yes, thanks, I had already found that helper function you prepared and it's a very good solution for a full-featured carousel. But sometimes what's required is just a quick "effect" style animation of a bunch of simple elements, not a full fledged application. 

Thanks again for your examples, I'm in awe of their elegance.

Now trying to figure out how to reverse direction with just one variable. 🤔

Link to comment
Share on other sites

1 hour ago, monospace said:

Now trying to figure out how to reverse direction with just one variable. 🤔

Okay, yeah, after messing with this a bit: wrong approach. It's easy enough to change orientation and direction, but to make it configurable requires a lot more code. Far more efficient for my purposes is to just modify the code as needed and then drop it in.

 

Link to comment
Share on other sites

23 minutes ago, monospace said:

Okay, yeah, after messing with this a bit: wrong approach. It's easy enough to change orientation and direction, but to make it configurable requires a lot more code. Far more efficient for my purposes is to just modify the code as needed and then drop it in.

 

I didn't quite follow what you meant - are you saying it was hard to make my code above configurable in terms of direction (horizontal/vertical)? 

 

Which code would you "modify as needed and then drop in"? The helper function stuff? Sorry, I'm a bit lost :) Do you need help figuring out how to reverse the direction in the code I provided above? 

Link to comment
Share on other sites

No, no, your code was clean and concise, and making those changes was easy. 
What I was trying to do was come up with a way to make those settings configurable, so that by passing a variable to the function, something along the lines of initCarousel('leftright'), or initCarousel('downup') , I would be able to re-use this without having to re-write it.
Again, easy enough, but that would have made the code longer again, and before you know it I might have ended up with something along the lines of your Helper Function: all good and fine, but it would have defeated my goal of having a small, clean snippet of code with a single purpose. 

So rather than making this configurable, if I ever need a version of this that moves, say, left-right, or up-down, I'll just modify it as needed and use it that way. 

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