Jump to content
Search Community

https://greensock.com/forums/topic/29426-3d-spinwheel-with-scrolltrigger/3D Spinwheel with scrollTrigger

lumuxd test
Moderator Tag

Go to solution Solved by Cassie,

Recommended Posts

Hi community,

 

I would like to code a 3D spinning wheel like the date picker on the iphone. It should be working by scrolling, so I tried to build it with the gsap tools and I thought it would be the easiest to use the scrollTrigger. I think it is possible and I probably have done it way to complicated. In my codepen example I animated the elements wb-item-1 to wb-item-6. You can see that it does not look realistic and not like a wheel as it should be.  

 

I also attached an image to understand what I want to achieve. It does not have to look like the appleUI but I want a realistic tilt- and scale effect.

Maybe you could help me here.

Thank you in advance!! :)

Screenshot 2021-09-13 at 19.16.16.png

See the Pen wveebwW by MarcelDiedrich (@MarcelDiedrich) on CodePen

Link to comment
Share on other sites

To take advantages of perspective in CSS 3D transforms you'll need to add a perspective to a parent of the elements you're transforming, and a translateZ to set a rotational axle.

 

Each of the faces of this cube are transformed like that:

See the Pen RwoBQaJ by ryan_labar (@ryan_labar) on CodePen

 

you may need to do some math to distribute your items (or a stagger with a linear easing could work!) on the cylinder.


Tip: Work on getting your animation running first, then add ScrollTrigger to control it.

  • Like 4
Link to comment
Share on other sites

Sure - you can use scrollTrigger plugin -

 

https://greensock.com/docs/v3/Plugins/ScrollTrigger

It could be as simple as adding a scrollTrigger into your params. Like so...

 

gsap.to(wheel, {
  rotationX: -360,
  duration: 8,
  ease: 'none',
  repeat: -1,
  transformOrigin: "50% 50%",
  scrollTrigger: wheel,// start the animation when wheel enters the viewport (once)
});


 

  • Like 1
Link to comment
Share on other sites

2 hours ago, lumuxd said:

do you know how I can trigger this by scroll and not automated?

gsap.to(wheel, {
	rotationX: -360,
	duration: 8,
	ease: 'none',
	transformOrigin: "50% 50%",
  scrollTrigger: {
    pin: '.container',
    trigger: '.container',
    start: 'center center',
    end: '+=100%',
    markers: true,
    scrub: 1,
  }
});

You'll want to remove therepeat: -1, then add a scrub: true, you could set your animation to pin in the center of the page (above code) or just scrub through as you scroll past it, depending on your start/end/pin settings....

Link to comment
Share on other sites

5 hours ago, lumuxd said:

I knew that css can build a cube but I did not knew that you can also make a cylinder?

Easiest way to approach this would be to get the height of one of the lines of text, and multiply that by the number of lines to get your total "circumference" and since c = 2 * pi * r we can get our radius (translateZ) by dividing your circumference by 2 * pi, then you'll get the angle index of each by dividing the total number of lines you have by 360, and use that as your += rotateX value. Obviously since it's more a polygon, you may need to tweek your translateZ a bit.

  • Like 1
Link to comment
Share on other sites

If you take a look in the console you'll see it was prompting you to register the plugin. 👀

gsap.registerPlugin(ScrollTrigger);

In future make sure to check the console for errors before asking for help - it should be the first step while debugging!

See the Pen dyRVPPz?editors=1011 by GreenSock (@GreenSock) on CodePen



You'll also need to either make the page longer in your css so you can scroll or provide a relative value like end: "+=2000px",

That will add some padding so you can scroll.

If you add markers:true you can see where the start and end markers are

Edited by Cassie
capitalise ScrollTrigger
  • Like 4
Link to comment
Share on other sites

56 minutes ago, Cassie said:

If you take a look in the console you'll see it was prompting you to register the plugin. 👀

gsap.registerPlugin(scrollTrigger);

Just one minor correction - ScrollTrigger should be capitalized when registering the plugin:

// BAD
gsap.registerPlugin(scrollTrigger);

// GOOD
gsap.registerPlugin(ScrollTrigger);

 

  • Like 2
Link to comment
Share on other sites

@Cassie thank you, that works perfectly for me! There are some things I want to change but I don't know how. I improved my own version which I posted here yesterday. There you can see that I want the page to be scrollable without any limit, so it appears like a real wheel. Additionally I would like to be able to change every single word. So I don't need the Script which duplicates the word "gsap". I don't know how to change that. 

Last but not least, the words should snap in the center of the page, so there is always any word in the middle. Then, a background-video of the body should change every time the word changes.

 

I would be so happy if you could help me, I tried my best but would like to use gsap as best as possible! :) 

 

Here's my code and I would like to use the cylinder mechanics of the other codePen.

 

 

  • Like 1
Link to comment
Share on other sites

The clone text function is just adding more text. You can add text into the DOM instead and omit that function, as long as the number of lines match up in the JS.

 

See the Pen MWoEeyP?editors=1011 by GreenSock (@GreenSock) on CodePen



In terms of helping you add the cylinder mechanics to your pen - You have 1300 lines of JS in your pen that aren't needed.

My advice would be to start fresh. Look at the demo we provided, read it, google bits you're unsure about and if you get stuck - we're here and happy to answer any GSAP-specific questions.

  • Like 4
Link to comment
Share on other sites

Hi @Cassie, thank you very much for the changes and the explanation!

 

As you recommended, I started from scratch and used your last codepen changes. In my edited codepen I already have changed everything to my preferred solution. 

 

I just tried to use the snap() feature and the toggleClass feature. The snapping works more or less but I think there is still an issue when I resize my browser e.g.. Do you know what I have to change here, so that the page snaps every word in center of the page?


Additionally I tried to use toggleClass to detect when a word is in the middle of the page. Every word should call the body to change to a different bg-video. In my codepen I test this by changing the color of the word. But it did not worked correctly yet.

Is that useful or is there a better solution to make this possible?

 

Thank you for your help! :) 

 

 

Link to comment
Share on other sites

Heya! No worries, glad you got it working. Good job.

So - I guess your snap is working but I'm not entirely sure how as it's separate from your scrollTrigger? 👀

Maybe it's setting it globally? - I'll have to poke around to figure out why as I would assume it wouldn't work like this.

I would have put it within your scrollTrigger like so...
 

scrollTrigger: {
    trigger: '.container',
    start: "center center",
    end: "+=20000px",
    markers: true,
    scrub: .5,
    pin: true,
    ease: "none",
    snap: {
	   snapTo: 1 / 264,
	   duration: 0.5
	 }
  }


I'm not certain what your logic for the snapping is. I've adjusted it to make a little more sense -  You have 33 sections so the snapping should be 1 / 33 

Additionally - you can't really track the positions of the elements with a separate trigger because they're moving around and the trigger will only fire when you hit their initial position on the page. 

It'll be much more bulletproof and more simple to use the callback provided within snap. 🥳

Hope this helps, happy tweening.

See the Pen ExXojRo?editors=0011 by GreenSock (@GreenSock) on CodePen

Link to comment
Share on other sites

Hey @Cassie thank you, that's very helpful!

 

You're right, It makes totally sense to put the snapping into the same scrollTrigger. I adjusted the second number because I once changed "rotationX: -360" on the gsap.to(wheel) to "rotationX: -4000" so the wheel can spin around multiple times. But I didn't thought about the consequences on the snapping...

Do you maybe have an idea how I can make the wheel infinitely scrollable? I tried the following code which worked perfectly on my previous version but it seems not to work in combination with GSAP.

window.onscroll = function(ev) {
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
 
window.scrollTo(0, 0);
}
};

 

To use the callback within snap is a perfect solution – thanks! But I can still only call one function and not a different for any single word, right?

 

Thank you again for your time, you're helping me a lot. :) 

Link to comment
Share on other sites

You could log out the progress inside that function and then create some custom logic to show certain images or videos based on the number that's returned?

See the Pen ExXojRo?editors=0011 by GreenSock (@GreenSock) on CodePen



I'm afraid I've never attempted infinite scroll but maybe this article can help:

https://css-tricks.com/going-meta-gsap-the-quest-for-perfect-infinite-scrolling/

Link to comment
Share on other sites

That would be a perfect solution for me!

Would you mind to enter a few more lines so I know how I can insert a function based on the progress-value? :)

I tried the following but there is a problem with it:

if (scrollTrigger.progress == 0.030250048487497575) {
}

 

Thank your for the infinite scroll reference - I used some code from there and it worked instantly.

 

Thanks @Cassie

Link to comment
Share on other sites

Hi again Lumuxd.

 

I'm afraid that suggestion was just that - a suggestion. I wouldn't be able to come up with a solution to this without a considerable sit down and a long think!

We've gradually gone out of GSAP-related territory and into 'custom logic' and I'm afraid It's a bit out of the scope of these forums to help with this.

In terms of steps -

You'll need to work out what you're trying to do - find out what values you can get back - and then figure out how to turn those values into something useable that you can hook into for your purpose.

Why don't you give it a go? You have to break things a ton before they work, don't get discouraged if you try a line of code and it doesn't immediately do what you want!

Obviously if someone has the time to help here - feel free to jump in.

Link to comment
Share on other sites

2 hours ago, lumuxd said:

I tried the following but there is a problem with it:

if (scrollTrigger.progress == 0.030250048487497575) {
}

 

Just a tip: that code will almost never work because the chances that the update will happen at that EXACT moment when the progress is precisely 0.030250048487497575 are almost 0. Remember, updates happen roughly 60 times per second, so the progress may be 0.01 on one update and then the next update it's 0.02457 or whatever. You should never code it so that it only runs at a very specific value like that  - you want to sense when it passes (or lands on) that value, so compare the previous and current progress. That means you'll need to maintain a variable that tracks the previous progress in that case. 

 

Or just place callbacks on a timeline and let it do that work for you. 

 

Good luck. 

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