Build a 3D Animated Cube using Three.js, Next.js and Framer Motion

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up guys welcome back today we are taking a look at the basics of 3D we're going to take a look at how to make a cube and then we'll animate it using different gestures like the drag the mouse move event and the scroll event we'll take a look at how to do that using 3GS firm emotion and nextges and after that I'm pretty confident you'll have a decent idea on how to animate 3D objects and as always the live demo and the source code are both available in the description below alright so I have a basic nextges application I've created a cube components and I've imported it inside of the page.js and the first thing I want to do here is start by installing all the dependencies that I'm going to need for this tutorial so I'm going to open the terminal here the first dependency we'll need here is react 3 fibers so we can go ahead here and install its app react 3 and then slash fiber and we'll also need the react 3 Dre we'll need firmer motion and firm motion 3D as well and finally we'll need SAS the very first thing we need to initialize a 3D scene is a canvas and then we can create another component I'm going to call it a cube and that Cube function will be able to return here and I'm just going to return a mesh and the mesh here will be recognized by react 3 fiber because it's inside the canvas and so it will act as a 3Gs mesh and then the mesh need the geometry to create a cube we can have here a box geometry and if we save that we're going to have an error because all of this code is basically client-side code and so it's going to trigger an error since we're in nextges and so the thing we need to do is make here our Cube components a client-side component by using the use client directive like this and we see that we now have like a very small cube here and now I'm going to add some styling to make the canvas take the full height and the full width of the window so inside of the page yes here I have the main I'm just gonna take it out here and I'm just going to go directly here inside of the cube and I can import the Styles here and I can specify that it should have a height of 100 viewport height and now we can see that our cube is now centered this looks a bit better but it's still a bit small for my own taste and so what we can do here is go inside of the args and here we can see that the RX is asking for a width a height and a depth which is basically basically the three sides of a cube right and so we could do one one and if we do that it's the default nothing will change and then I'm just going to boost it to like 2.5 and that should basically scale it by 2.5 and now we have like a much bigger Cube which is kind of the size that I'm looking for here and now I can add a color to the cube so I can use here a mesh standard material and I can give it a color and I'm just going to do like orange and if I save that I can see that I have a black Cube and it's like why is it black if I put an orange color right the reason is our scene is black it's like we're in like a cavern so we need to create an ambient light and then I can have like an intensity and I can do like two and now I have some light inside of the cavern and I can see the color and then I kind of want to see that we have a cube because right now it looks like a plane it looks like a 2d plane I'm not really sure what's going on I'd like to see it as a cube so what I'm gonna do is make it rotate at every single frame just to see what's going on a bit more clearly so what I can do here is import the use frame Hook from react 3 fiber and I can initialize here the use frame hook it's going to give me two things the state and the Delta and I can trigger a function here and now this function will be called at every single frame and then if I want to rotate my mesh I can create here a mesh ref and I'll use the use ref Hook from react and I can take it go inside of the react here and import the use ref and then I can give the mesh as a reference here to the mesh and now to rotate the cube out every single frame I can do mesh dot current dot rotation and I can access like the x-axis and I can do plus equal the Delta and I can like do multiply it by 0.1 just so that it's not rotating too fast I'm just going to do the same thing for the other axis so the y-axis and the z-axis and if I save this I have the cube rotating I'm just going to make it a bit faster here and here we can see that we have a cube but since we have just an ambient light we don't have any Shadows so it's kind of giving me a headache when I look at it it's like we don't really nicely see the 3D perspective so one thing we can do is add a directional light so I'm going to add here a directional light and I can have a position and now when we want to start setting the positions of elements inside of the canvas it's important to understand the coordinate system so I have here the coordinate system of 3GS and you can see here that it uses a right-handed coordinate frame right and so we can see that the right-handed Cartesian here we have the Zed pointing towards us the X to the right and Y up and so with that we can put the lighting at a proper place the first axis is the X and I can do like two so two is going to be on the right and then I have the Y which is on top I can have like one and then the Z is towards us so I can have like one to have it in front of us and I can save that and see what we have and we have a bit of a shadow here and so we can see that the light is like here and it's pointing down and giving a light here and a shadow on the other side right so now that's pretty good it's helping us to understand like the 3D perspective here and then there's one thing that's itching me I can see that I'm scrolling here so I'm just gonna go in the globals go inside of the body and specify that it should have a margin of zero pixels and now I can see that I don't have the scrolling anymore and the next thing I want to do here is add a texture an orange color is really fine but I'd like to add an image so here I have a bunch of different images and a red square I'm just going to take them here inside of the public folder I'm going to create a NASA's folder and I'm just going to take this and put it inside and now to load the texture I need to import two methods one is going to be from react 3 fiber and it's going to be the use loader function and that use loader is going to load another loader which is the use texture and now in 3GS this use loader can use a bunch of different loaders and so we need to choose the one that's right for us and the one I'm gonna use for this tutorial is the texture loader I can import that from three Source loaders and then texture loader and then I can go here and I'm going to create here a cons texture one that's going to be equal to the use loader and I'm going to use the texture loader and I can go and I'm going to get here the color.png and then I can grab that texture and instead of having a color here I'm going to have a map and inside of the map here I can put the texture one and I'm going to save that and here I can see that that texture is being applied to every single faces of the cube so since it's red it's not the best example so I'm just going to change it to the one.jpg here and you're gonna see what I mean you do one.jpg and you're gonna see that that texture is going to be repeated on every single face of the cube and so that's something 3GS does automatically and now what if we want a different image on every single face of the cube it's going to be very easy instead of having one we're gonna have six so I'm gonna do three four five six and then here I'm just gonna copy paste as well two three four five six and if I save this we can see that it's not working we only have the last texture here the last mop is being applied to every single faces and so to fix that problem I'm gonna go here and use the attach props and I'm gonna use the material zero like this and this is kind of specifying that this is the material for a certain face and this is going to be the material for another face and we can do the same thing for the others that way we're basically telling three just hey use different textures for different faces I can see here that I have a cube with a different texture on every single faces and here we basically have our Cube and our lighting which is good so we can go ahead and start animating everything using gestures the first one I want to do is the drag gestures and this is going to be by far the easiest to do it we can import something called the orbit controls from react 3 Drake and this is super nice we can actually just drop it inside of the canvas and we can save this and if we try this we can see that I can now move my Cube around by dragging it and what's nice is there's like a damping that's automatically applied so like the cube is actually rotating in like a very smooth way which is really nice but there's a couple problems with that is one thing is we can actually zoom in which is maybe not what I want for this specific animation it could be nice if it was like maybe like an e-commerce and we want to like see the product closer or something like that but for the specific animation I don't really want to be able to zoom so what I can do here is go inside of the Orbit Control and say enabled zoom and I can just do false and now I can't zoom anymore but I can still move it around and there's another thing with the orbit controls that I don't want is if I use my right click of the mouse I can actually pan and like move the cube around like this which is also not something I want for this tutorial but you could wanted for like a different case and so to remove it I'm just going to do enable pan and I'm gonna do false and with that I have these simple drag animation and I've removed the zoom and the pan and now what I'd like to do is add a mouse move event gesture I basically want to be able to rotate the cube while moving my mouse around so I'm going to use frame motion for that I need a bunch of different hooks the first one I need is the use motion value and I'll also import the u-spring and then I'll just remove the animation inside of the use frame hook and now my cube is like static again and then what I can create here is a mouse object and inside of the mouse object I'm going to have a next value and I can have it as a motion value and I can have it equal to zero same thing for the Y use motion value equal to zero and then I'll grab a use effect hook and inside of it I'm going to initialize an event on the window and I'm gonna have the mouse move event which is going to call a manage multiple function and here I can return a window.remove event listener and then I'm just going to declare that manage Mouse move here it takes an event I can can extract from that event the client X and the client y from that event and I'll also grab here the inner width and the inner height of the window and then I can have here a Target X or actually I'm just going to call it X which is going to be equal to the client x divided by the inner width and same thing for the y-axis but this time for the inner height divided by the inner height and now those two values will be a value between 0 and 1 depending on the position of our cursor right so if we are here on the x value it's going to be 0 and if we are here it's going to be 1 on the y-axis if we are here it's going to be zero and if it's here it's going to be one right and then we can simply use those values to set the mouse so we can do mouse dot X and we can do set and we're going to set the x and then Mouse dot y dot set and by the way that set function comes from the use motion value object given to us by firmware motion so that's good now we can simply grab the mouse and we can go here inside of the mesh and we can have here a rotation Y which is going to be equal to the mouse dot X and then we can have a rotation X which is going to be equal to oh sorry mouse.x and for the Y Mouse dot Y and now this is a motion values so the mesh here won't be able to understand what the hell is a motion value so to make it understand we need to add here a motion in front of the mesh and now that motion we won't import it from the regular firmware motion package we're going to import it from the 3D package so the frame motion 3D and we can save this and if we try this we can see that we are now moving the cube with our Mouse there's a couple of things that are wrong here my axes are in the wrong direction which is for my personal taste when I move on the y-axis I'm actually rotating on the y-axis as well but I'm actually going to reverse that and so I can go here and reverse here so the rotation X will be based on the Y position and the rotation y will be based on the X position of the mouse so yeah that makes a bit more sense to me and now there's another thing that's weird if I have my mouse completely in the middle of the screen the cube is like rotated and that's because in the middle here on the x is 0.5 and on the Y is 0.5 so we give those values as a rotation and by the way the rotation values are in radians and that's why we can use directly like 0.5 and 1 and all of that but yeah personally I'd like to have in the middle here no rotation and so I'm just going to change those values here and I'm going to add here A minus 0.5 and I'm going to add that value here minus 0.5 now I'm going to add a value here as well for the y-axis and now if my mouse is in the middle of the screen there is no rotation applied to the cube which is what I want and now if I move left and right I can see that I'm now moving my cube when I move the mouse so that's really nice but there's one other thing that I don't like is the animation is not smooth it's like directly linked with the mouse right now which is not that nice personally I'd like to have it smooth just like the orbit controller is right if I move the Orbit Control we can see that it's actually like smooth but when I move the mouse then it's like not smooth so that's a bit of a problem for me so what we can do simply I'm gonna wrap the motion value inside side a u-spring hook which is also from Fair motion and the use spring will basically make that motion value smooth and here I'm going to create an option I can call it options and I can have a damping of 20 which is a value that I found is actually nice for this type of animation and I'm just going to add here the options for the use spring hook I can save that and I can see that when I move my mouse I'm actually moving the cube in a smooth way and then I have my Orbit Control and I can just move the cube around move it with my mouse as well and now the last thing I want to take a look at is the scroll gesture how to rotate that Cube on scroll this is like a very common animation that I see in a lot of award-winning websites so it's worth it to take a look at it there's actually two ways that I found that we can do this so there's one way using a Dre package and the other way is using firm emotion we're going to take a look at the two and you can use the one you prefer depending on your case so the first method of animating using the scroll is using the Drake package and I'm going to import here the scroll controls which is by far the easiest way of the two I can grab the score controls and I'm going to put the scroll controls here inside of the canvas and I'm going to wrap everything inside of it and I'm going to save that and here you can see that it added me like a scroll bar here that I can actually scroll and I can specify a number of pages and I can have like five pages and here you can see that I have five pages worth of scroll right and one page is equal to 100 viewport height and now it's like okay I have a scroll great but my cube is still not rotating still not moving on scroll so what I can do to start animating it is I'm going to go here in the react 3 Dre and I'm going to import the use scroll hook and then I'm going to go in my Cube here and I'm just going to take off this for now just so we don't get confused and I'm also going to take off the options here for the damping and now what I'm gonna have here is data that will come from the use scroll hook and then I want to access that data at every single frame so I can use the same hook that I used before the use frame and that use frame has the state and the Delta as parameters and then I can extract something from the data here and I'm going to extract the offset from the data given to us by the use scroll right and that use scroll is basically reading everything inside of these scroll controls here and now that offset is a number between 0 and 1 depending on the progress of the scroll right so at the beginning here it's going to be zero and at the end here it's going to be one and so now that we know that I'm just going to copy paste the code that we had here before for the rotation and instead of doing plus equal I'm just going to do equal to the offset and then I can multiply the offset by five just to have like a proper rotation and then I'm just going to take off this animation here which was from the mouse move event and I'm going to scroll down and you can see that I'm rotating my Cube on scroll and there's also like a damping that's automatically applied so that's really nice from the Dre package and if I want to change that damping I can go in the scroll controls here and change the damping and like put maybe 0.1 and here we can see that it kind of changed like the smoothness right but the default kind of was fine to me so yeah that would be one way of making an animation on scroll but personally even though it's a very easy way way of doing it it's not very adaptable like I can see some cases in like a real world context where that wouldn't be the best for me so we're going to take a look at another way of making this using the frame emotion hook the use scroll Hook from frame emotion which is in my opinion a bit more versatile even though it's going to be a bit more complicated so I'm going to take off the user scroll and the scroll controls here take that off now I'm going to take off this as well and instead I'm going to import here the U scroll from frame remotion and then the first thing I need here is a container ref which is going to be equal to the use ref Hook from react and I'm going to give the container here to the main and now my main here I can go inside of the styling and I can specify that it should have a height of 500 viewport height which is basically like Pages equal to five inside of these scroll controls that we had before and then I'm gonna add another div inside of it I'm going to call it the cube and I can specify that that Cube should be in position sticky with a top zero and a height of 100 deeper height and I can save that same as before I have now a scroll of five pages worth of scrolling and I have my 3D scene that's being sticky and now I can use the use scroll Hook from firm emotion and I'm going to extract from it the scroll live progress which is going to be equal to the use scroll Hook from frame of motion and here I can give it a Target which is the container meaning I want to track the scroll inside of the length of that container and then I need to specify an offset and here it's always a bit of a headache but the offset here is going to be the start of the window and the start of the container which is like the top position here so I can do start start and then when do I want to stop tracking is like all the way at the end which is here the bottom of the window and the bottom of the container so I can do end end and so now the scroll why progress will be a value between 0 and 1 at the top here being zero and not the bottom here being one and now what I could do is pass that scroll y progress to the cube here and I can call it progress and now that Cube has progress here and I can use it same as before I have the rotation Y which is going to be equal to the progress and the rotation X I can do this same equal to the progress and I can save this and if I try this I can scroll and I can see that my cube is rotating on scroll now a couple of problems it's not rotating a lot and that's because I'm directly using the scroll y progress here which is a value between 0 and 1 and that's not enough of a rotation to have like a nice effect and so what I need to do to transform that value I cannot just go here and do like multiply by five because this doesn't make sense the progress is a motion object and so we can't multiply an object by five this doesn't make sense so to actually transform that progress and multiply it we're gonna need to use the use transform Hood from thermal motion and here I can basically transform and I can have a progress and I'm gonna do the use transform and I'm going to transform the scroll wire progress which is the value between 0 and 1 and I want to transform that value into a value between 0 and 5. and I can use that progress as the progress instead of directly using the scroll wide progress here and if I try this I can see that I have now more of a proper rotation and so that's pretty good but there's another problem is the animation is not smooth a bit similar to the mouse move event problem that we had before we can solve it very easily by having here a smooth progress and I'm just gonna have the U spring of the progress and then I can use that smooth progress for the progress here and I can save that and I have this and if I scroll I have my Cube now you can see that there's like a sling slingy animation so I just need to change the options here I'm gonna have the same options here with the damping 20 I can go here in the u-spring and I can add damping 20 just to modify that use print value to have like a nice animation a nice smoothness and if you try this we have a rotation on scroll so yeah that basically concludes this tutorial we've seen a mouse move event a scroll event a drag event and we've seen how to create a basic mesh with a texture I hope you learned a lot if you liked the video leave a like subscribe and I'll see in the next one bye
Info
Channel: Olivier Larose
Views: 13,191
Rating: undefined out of 5
Keywords:
Id: 9XvZ3ChtT9M
Channel Id: undefined
Length: 19min 2sec (1142 seconds)
Published: Thu Sep 14 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.