Transcript for:
Building a Professional 3D Portfolio with React 3 Fiber (Part 3)

how to build a professional looking 3D portfolio with react 3 fiber part 3. hello today we will create the HTML content with Tailwind display a custom mouth cursor and add 2D 3D scroll animations using framer motion what we will do is recreate the HTML interface you can see here reproduce the menu the cursor and the scroll animation so from one section to another but also fading items making them appears we'll start from this charger pack again but I think it's the last time we start from scratch we are going to start playing Lego with the room we baked and also the Avatar go to code copy and go to visual studio code git clone and the folder I want to put in let's name it final now we have it let's open it run yarn and yarn Dev we now have this moving Cube which means it's ready for the HTML interface I decided to go with Tailwind because it's something I like I know some people don't like Tailwind it's not mandatory because later we'll use frame remission that is a framework agnostic you can use with whatever shoes you make let's follow the documentation to install Tailwind CSS with the bits we already have our project we need to install our dependencies available here yarn add to save dependencies only for development purpose at dash dash Dev and paste okay now what we need to do is to run init from Tailwind CSS let's do it and then we need to add in our Tailwind config file this line let's go to it Tailwind config content it means the target where we want to add the Tailwinds or the index and the JS file at the beginning of our CSS file we need to add those three lines index.css add those lines now let's check that it works copy this go to app.jsx next to the canvas we can add some HTML but we have our canvas in front let's remove it or on this div okay so we have hello world it's a big text or text 3XL font bold it's bold and it's underline which means it worked let's have a look at what content we want to create if we go to the menu we have home about work and contact we will do almost the same which means four pages as we don't want to remove every time the canvas and have the content on top of the canvas we will use scroll controls we will wrap our contents inside and we will use scroll HTML to put all our Pages inside how does it work we need to wrap everything with scroll controls let's put it here and wrap experience inside we need to import it from dry we need four pages as we saw and the damping we can leave it like this then we will want to have a score container for our HTML we'll use scroll and add the prop HTML now we can add our content inside now let's check if it works we have Hello World on top of the canvas but I can scroll because of the Orbit Control catching the scroll go to experience we can just get rid of it now I can scroll and the height of the score is like four pages so four times the height of the screen we will put our content inside a new component we will create components name it interface.jsx export const interfaced in up we can get rid of it import our interface we want to have four sections full height let's create it let's first create a component named section it will take the children's as a prop it will return an HTML section and the children now we will have our four section the first one is home well it's about kills projects and contact so but we have no CSS the content is on the top left of the page let's fix it to add CSS with Tailwind we need to use classes so use the Prop class name and add all the classes you want each class refers to a CSS property to make it easier to make it multi-line we can use this and back code we want it to be full hate full with we add some padding we set a Max waste so it's not on big screen too big 2XL we Center it automatically with MX Auto we set it to flex Flex column and we put the items on the left with item start and justify Center to Middle all you need okay now we have full height section but the centering isn't correct we are missing a wrapper here we can go at a div class name Flex call items Center and we need it to be with a full or with screen and now the section can be too big we always have space let's make it even cleaner we can create one component per section about section will have a section component and inside add our thing about section now let's create our real content for the about what I prepare is a big title hi I'm over Sensei some text below gray and a bit of margin learn how to build 3D apps and a button blue background with white text with contact me here is what it looks like of course customize it now let's jump to the skills section inside this section we will display our skills and languages I created an array with the different skills we have so we'll Loop over them to display some HTML and same for the language of course put your real skills and languages here is what we have chaos a title with a block under we Loop through all our skills and we set the skill title and we have a fake progress bar here with the with defined by the percentage of level you assigned and the same for the languages we Loop through all items and the progress is available here this is what it looks like and we will animate it later today we will skip the project section we will do something fancy in the next tutorial and we will do the contact Section I just created something simple with a title a form with a name email and a message and then the submit button so far what we have now is this section then the skills projects it's empty and contact me I'm not spending time explaining Tailwind but just one useful thing is the extension which is intellisense for Tailwind so if you write stuff it automatically auto complete and tell you what CSS is applied so it's a very useful if you go to extensions search for Tailwind intellisense you will find it the library that we will use for animation is the famous framer motion it comes with many options so either you are doing a duration based animation based on scroll or on different stuff it's based on the time so it's good for fading effects but for realistic effect there are spring animations and it's also available with primer motion for example if we move here you can see it's a realistic effect like a real animation not just fading the value between one another to install it it's a very easy the yarn add framer motion but also there is the motion 3D available that we'll use later so let's install it right now we have nothing more to do we can directly use framework motion to use framer motion we need to add motion dot the component but the Auto Import doesn't work so I will import it motion from primer motion now thanks to motion I can add some new props to make animation on this section we will use initial to say it's coming from those value I will say opacity 0 so we will make it fade in and also affect the Y position we will put it slightly below so it will fade up now what we want to do is to animate it when it's visible on screen we can use the prop while in view you can see there are many different options available and what we will do is obesity on one and the Y to zero if I reload you can see it fading and it's a very fast this one I didn't have the time to see it so let's add some parameters to effect the transition let's switch it to a time frame based animation add transition set a duration when you do it it goes from Spring 1 to time frame based and we will add a delay so we have time to see it happen now let's reload hi I'm MOA Sensei it's fading same for the second section projects it's not a section and contact me too perfect but to add more life to it we will animate each item independently in top of the section if we go to the about section let's say I want to animate this one I add motion dot p now I have access to the motion props I can say initial opacity 0 and the Y will say a bit 25 and when it appears while in view we'll say the Obesity to one the Y to zero and let's also change the transition to add more daily than the section so a duration of one two but a delay of 1.5 let's do the same for the button we can copy all of it motion that but on and we'll just increase the delay so items will appear one after the other let's reload hi I'm more Sensei I make YouTube videos contact me let's do the same for the skills for each kill we will animate the title and then initial we'll just make it fading and while in view opacity to what and the transition the duration of 1 and we will set a delay to once again plus we will add the indexed multiplied by 0.2 what it will do is each skill will show one after the other because the index will increment for each let's do the animation for the progress bar We'll add motion dot div initial will set the scale X to Zero and set the origin X to Zero and then when it's in view we'll set the scalics to 1 and we also add a transition of one and a delay the same concept let's have a look at what we have here if I scroll it's fading nicely and the progress is fine but what happens if I come from the bottom it will play again but let's stop here and then scroll later you can see the order is uh the wrong one because I want it to start from the top to the bottom but the first items to be in view are the one from the bottom for this we can use something named variants on frame or motion so what we will do is on the whole container on the main div we will transform it to a motion dot div we will say while in view and we will name it visible it's a variant name and now instead of setting each item based on the wider in view we will Define what is name variance and for the visible variant we will set our style opacity to 1. and inside our variant we can set the transition so here we can also Define our transition we don't need the widen view anymore let's do the same here the while in view we want variance the variant is visible we want the scale X to be one and we want that transition I will write it manually here scalex and transition now if I go from the top it works nice and if I come from the bottom it plays also from the top perfect variants are very powerful you can use multiple variants and use it from the top of your project to inject it on a very low children we need to do the same for the language so maybe it's it will be faster to just copy paste here and languages are here just it's not skill it's LNG okay but because uh the language or below we want to animate them later so set the delay to two so far what do we have skiers and then language is nice before jumping to the 3D part there are two things I want us to do is when we start scrolling it directly jumped to the second section and then we can scroll but if I go here and I go to the second to the first it also jumped back to the top of the page we will do it and just after we will do the menu to make it we will create a custom component first I want to know in my project what section we are currently display it will be useful for the 3D also so section and set section it means where are we are we on the about project contact use date of zero then we will create on top of scroll controls the component name scroll manager really important when it's created we will pass it in the section and on Section change it will call the set section to update our section it will be responsible of this let's create this component components crawl section a scrollmanager.jsx it will take props it will have section and on Section change from the props perfect in our app we can now use it I tried different approach to do it first we are using use scroll for one reason it's because we want to have this smooth effect when we scroll it smoothly fade in our page using I use scroll with 3D is very useful we could use a scroll trigger from jsap but it's a bit too much to achieve these results and we can do it just with the score position but we will use jsfp to make the smooth animation from the first section to the zero and the zero to the one maybe let's install it right now yarn add jsap what we will need is to have the data from you scroll to know where we are currently scrolling and to have access to the container element that Scrolls we will store the last call position we store it in a reference to prevent a re-render and we will check if we are currently animating to avoid impacting it while we are performing the animation and by default let's set it to false then we will use use frame to check our conditions so are we animating if we are animating we won't do nothing but we will still want to store the last scroll position so last crawl that current equal to data scroll dot current then if it's not the case now we can try to add our logic let's find what section we are currently in to do so we add mat dot floor we check the data dot scroll dot current multiplayer multiplied by the number of pages we have as it's a percentage of score from zero to one and the number of pages so we will know at what page we are so if the current scroll is over the last scroll and the current section is zero and if our current scroll is below the last scroll but we want it to happen only if we are reaching the first section to know it we need to do the current scroll is below 1 divided by the number of pages minus one in that case we call on Section change to zero okay so now it will change our section what we need to do is when the section change we we trigger our animation let's go on section we use effect that we trigger our animation here but just before here we need to store the last crawl if not it will never work so let's get back to when the section change we will trigger a jsap animation we will set two the container is data.l it's the element returned by U scroll what we do then is a duration of one we animate the scroll top by the section multiplied by data dot l dot client hate it's the total um hate scroll label to prevent aor we add onstart is animating to true and on complete is animating to false there's the comma missing perfect let's have a look at what we have I start scrolling it automatically scroll down but we can see it's not scrolling perfectly if I scroll down it's fine I can scroll as usual if I go up then when I reach a certain threshold it goes back to the first one it's good but we need to add a fix I did some research and I found that the CSS made by you scroll is uh wrong maybe it's because of Tailwind impacting it but we can add some fix and it's quite easy when we add a scroll controls here with a number of pages a use card creates an element made of four times the height of the screen but for a weird reason it appears it's like five but we can fix it by accessing it like data dot fill and we will add some class to make it sure that it's a position at the correct position we add top to zero and we also add absolute position so now it really feels the whole screen at the correct spot now if we reload we start scrolling and it's perfectly aligned on the middle of the screen if we go to the top same applies let's add the menu button but thanks to Tailwind it will be very fast let's create next to our canva menu components go to components create menu.jsx what we need to have access to in menu is to change the section to scroll to it so on Section change equal to set section okay now let's go to our menu exports const menu equal we have access to on Section change that we get from the props and we will return some HTML stuff here nice now we import it and let's code our menu oh we will need another prop is is the menu opened and set if the menu is open we could have the logic in the menu but we want to have access to it in the 3D part later to animate the camera let's define here a menu set menu open by default it's false and let's add menu opened and set menu open okay now in our menu we have access to it we can start coding it I've created a simple button I added some logic when the menu is open it will translate to make it across to be able to close it let's add on click we toggle if the menu is open let's have a look at it we have the button here if we click maybe I need to reload it doesn't call the middle let's see why here it looks like it's correct and here oh menu open it's menu opens should be better now okay if I click it open and close the menu now create the menu I added a fixed width here with a width of 80 when it's open and 0 when it's closed I added transition to make it smoothly transition from 80 to 0. and inside the world position are many button later here we have our menu opening and closing here let's create a menu button component it's just a button with a on click event and a hover a color changing we will add all our menu button here we have the about skills project and contact when we click on it it will call set section with the number to scroll to but here it's set section and the prop is name on Section change so it should be this now we can go open it and change the section just by clicking on it in the application let's add a use effect on if the menu open change if the section change we will set menu open to false to automatically close the menu why it's better to do it in a use effect than on the on click because now if we scroll and it automatically scroll it also close in the menu and it works perfectly now it starts playing some Lego by adding our scene and our Avatar in the portfolio animation tutorial we can go to animations paste it to our public folder let's also get the models we won't need the fbx it was just for mixamo so let's get rid of it and now let's go to the baking project it was here public models we also need the scene which is the baked one and we need the textures by the way we also need the components so we need the office components Source components here is the office and on the animation we will also need our Avatar components thanks to react it's very easy to add components and items from one project to another let's go to our experience now we just have the cube but not for long let's add an ambient light with an intensity of 1 and let's load our office component it doesn't know it because it's freshly added to the project do you know it now no so I will import it manually Imports office from office looks like it's here but the camera is at the wrong place let's change it to zero three 10 and a bigger field of view looks way better nice I will also change the background color to something bluish but maybe we'll change it later and later we'll do some animation with the background let's position and scale our office wrap it into a group choose a position I ended up with this one Let's Skate it a bit down slightly rotate it on the y-axis to minus mat dot p on four we are putting it on the top to animate it to go at the perfect place how to animate 3D elements with a frame or motion it's the same concept add motion Dot and now we have access to the prop to animate but we need to import it manually to from framer motion perfect and animate we will add an animation on the Y and what we will do is if the section were currently is zero then we will put the Z position the Y position to zero if it's not the case we set it to -1 we will pass the section to the props const section equal props by the way it's like this jump to the app and experience now need the section prop it's available here okay it doesn't work this is because we are using framework motion import here while we need framework motion 3D for group and 3js related things now if I reload we have this if we scroll it goes down okay but I'm not happy with the animation I want to change it I've showed you before we can set the transition here and Define the configuration but I want to define a default animation type for all the rest of that thing we will do and to do so we can go to the up and wrap everything into a motion group by the way it's motion config and okay now everything I will set an animation to will have the motion config transition animation set unless I Define it specifically for one item so the default one I want is a spring one with a mass of five stiffness of 50. a damping off 50 and a rest Delta to 0.0001 of course have a look to the documentation for the explanation of those parameters and try with different values and see how it react and this is way too slow maybe I've made a mistake okay stiffness is 500 let's load it oh now it's more Dynamic when I move it okay fine but what I want to do is I don't want to see this forever so what I will do is on at the 3D models to add a scroll from your scroll same as we did for the HTML so it scroll alone we can wrap everything into scroll component and now when I will reload when I scroll it scroll to I don't see it anymore I have the animation and stuff happen okay now let's have a look at how we can make the item scales up and down as it happen in the office we need the section in the office too go into office get also uh the section from the props let's import motion from the correct place this time framer motion 3D and let's hop in here I decided to just animate some items to make it go from small to to big size and to have a nice animation like in David heck of one uh lava lamp we can switch to a motion group and we will add an animation so we'll animate the scale if the section is zero it will be one if it's not the case it will be zero and close the animation we will do it for a lot of item so what we can do is by default uh set the scale to zero and animate I put it just next to it so if I want to do replace it will be easier let's look first if it works on the lava lamp if I reload I can see it's happening but because it's the smallest object I chose it's difficult to see but it works let's make it on the rug copy paste but here it's motion dot group while it's a mesh so just update this then where can we do it we have the Pokemon here Sarah mesh okay the same let's make it on the iMac here perfect then we have the plant where is it here let's make it on the houseplant as well be careful to close with motion.group but automatically it works on my visual studio hope yours as well my favorite item the palm tree the chair and that's it for now I'm not very funny I'm using the same animation the same parameters but of course you can be from your animate the position do whatever fits your your goals but keep in mind that we baked the Shadows so it can have some weird results by the way copilot taught me 0.5 for the scale but it's not what I wanted I want zero that's why it was barely noticeable so let's change it okay should be better now if I scroll it disappear and if I scroll up you can see it's jumping so it's a nice effect I like it but when I scroll down the item disappears and the Shadows are making it very weird I I found a quicker round to to this is to fade that texture here and we can use a framework motion too now change our texture material to transparent through about the opacity by default will be one now we will create some framer motion values we will have texture opacity it's equal to motion value of 0 by default we don't want to see it we also do it on the glass because it's the same let's name it glass texture obesity what we will do is a use effect when the section change now what we do is we call animate from framer motion on the texture opacity if the section is zero it will set it to 1 and if it's another section the opacity will be zero that's fine we don't need extra parameter and in the same for the glass texture opacity now what we need to do is to really update on every frame our opacity of the texture to do it use frame and we have access to our texture so by default it says there thank you copy a lot you know everything so we have the opacity on our material we get the value from the framework motion value using the get method and we do it for both materials and now what we have is the item fading and Fade Out it's quite nice but the glass has an issue because it's not transparent anymore because here it should be the initial value which was before 0.40 no not here here it's not never one it's the maximum should be 0.42 and now it looks like this pretty nice let's add the Avatar and some more items just to to go further on the project our skill sections I prepare something very easy it's a light with floating uh sphere and uh Cube just look I used a mesh distorts material from dry it has a nice effect you will see it in action I also used a mesh wobble material it also have a nice animated effect while doing pretty nothing and I added the Avatar if the animation is the default one is tending uh well it's standing after and by default it's falling but later in the project we will make it sit in front of the computer so it's not very important nice let's do all the required Imports and let's look at it but we have an error because Avatar is using Leva and we don't have it let's add it to our project yarn add lever and I want to hide it so next here we can set a level and hidden to not see it and we also want to wrap all this section into a group here and here I can see it but it's on the right we have an issue I think it's because oh it's in the other group this is the problem it shouldn't be in this office group but after now we can see it in the background and if we scroll it's not at the correct position here let's look how to make it very aligned with our skills position we want to have it in the background on the first section and then to go in front of us to do it we can add a motion group to animate it and for the animates we will set the Z position if it's on the section one we will set to zero or -10 and for the Y we will use is intersection one so the skills section we will set it to minus viewport dot hate if it's not the case we use minus 1.5 viewport.hate is the very useful one because it's the height of the screen we get it from use three const viewport from use three so now when we use uh viewportate we know it will be perfectly centered based on the height of our screen now look how cool it is we have our character in the background falling and the weird bubble Distortion and when we scroll it's perfectly centered in our screen we have this effect but because it's in a scroll container we can scroll it and it scroll along and it disappears so it leaves space for later we add some stuff to our project because we never stop copying David or David I don't know how to pronounce it you can open the menu and see the camera moves it adds more connection between the two to the UI and the 3D let's do the same what we need is to pass the information do the experience if the menu is opened or not add a new prop in our experience let's get this prop value menu opened and as we did for the texture we will use motion value camera position equal to motion value and camera look at it exposition then in a use effect when the menu open change we will animate our values what do we have here nokopilot is not what we want to do what we want to do is to do animate on the camera position X if the menu is opened or not we will set it to -5 or 0. we'll do for a look at about inset to look at -5 we will look at five or keep zero which was the default value and in a use frame we will apply builds value we will need the state and apply it so what does copilot say state that camera position dot x equal to camera position x dot get this is correct and look at on the X it's the value and 0 0 is the default one perfect here if we apply it open and transition but the animation isn't the same motion config that we Define maybe it doesn't work with animate what we will need to do is to pass a third parameter which will be our config but I don't want to write it again what we can do is to create a variable with our config so let's say here it will be our config let's create a new file config.js export const framer motion config equal to this and now we can use framework motion config that we just created but we need to import it it's import ant from uh is it here yes oh I named it in correct it's framer motion config here it is framer motion config and here too better now in our experience we can do the same framework motion config and here too as well so we have one config available everywhere we can change it from here it applies everywhere now if we open the menu or close it we have that nice effect looks pretty cool just stop bonus before finishing for today we will add a nice cursor to create it let's create a new component named cursor curse or equal return okay let's add it next to anything yeah yeah maybe here cursor and let's call it the logic here I won't code everything here because I already did it in a previous tutorial and I'm using the same component it's in the Christmas tutorial I think let me explain a bit the logic here the HTML we have is an element fixed that will follow our cursor but slowly we have a conditional case when it's of hover hovering a button the background will change and it will be a border if not it's just a bubble we are listening to mouse event listener so when it's a move we follow the position smoothly there's all this logic here where we calculate the distance between our cursor and the previous position to smoothly catch up with this p and the only thing I added is if we are hovering a button it will set the state to hovering a button so the CSS will change but I also added if the parent of an element is a button for the menu bars and also if it's on an input or a text area for the contact form let's have a look at what it looks like now if you look we have this small dot following us of course you can customize it if it's hover contact me you can see it's a black circle over but if I go back it transform back to its original state it worked also for the menu button here as well which adds some beautiful experience stuff if I go to the contact form same for the name email and message foreign thank you for watching I hope you enjoyed this video please hit the like button to help the channel grows and gain visibility I also added YouTube memberships to the channel if ever you want to support my work I will be forever grateful next episodes will be the final one to have a complete port for you if you want to continue learning and improving your reactory fiber skills jump to the next video by clicking here