React 3D Animation Website Tutorial with ThreeJS (WebGi) & GSAP

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this course slow button will teach you how to incorporate 3D models into your react websites and product pages slow button is a senior full stack developer and popular course creator and welcome to this tutorial in this one you're gonna learn how to create this amazing react website with astonishing 3D animations we are gonna learn how to use webgi SDK to manipulate and find your 3D models then we're gonna learn how to display them in your website using webgi and 3js and then we're gonna learn how to animate these 3D models using gsap and webgi we are also going to create this preview mode where visitors can play around with their 3D model and apart from that we're gonna learn how to optimize these animations for mobile devices and at the end we're going to build this project and deploy so be ready to learn a ton of stuff some prerequisites for this tutorial is to have basic HTML CSS and JavaScript knowledge if this video reaches 1000 likes on my channel I will be releasing the full source code on my GitHub otherwise you may want to check patreon.com for my support and full source code so what are you waiting let's get yourself comfortable and let's start code with slova and welcome back so this is the website that we're gonna be building in this tutorial the first thing that we need to do is to head over to github.com here I have created these 3D website startup package for you guys the URL of this repository is going to be in the description box below but you can see the URL here as well so what we need to do here is to download this package this way it's going to be very easy for us to set up the project and get going with programming so head over to this code button and click on it there are multiple ways to download this repository but the easiest way is to download a zip so click here download zip wait for a couple of seconds and the file has been downloaded now let's find it in the file explorer so click on the Explorer icon and in my case it's in the downloads folder now let's right click on it and extract here so we want to extract the content of this folder now open this folder in your code editor for me it's Visual Studio code so open the visual studio code file open folder downloads and iPhone 3D website starter Dash Main I will click yes I trust the authors let me zoom in this a little bit and let's see what we have generated in this Repository first you have this public folder on top here are all the files that you don't want to import using the module system in your application so this could be the files that you import dynamically the next folder is the source folder essentially this is the core of our application inside of the source we have this assets folder as well in this folder you can store images svgs fonts whatever you need all the images that we are going to be using for this website are already downloaded and set here so you don't have the bottle with downloading separately next we have this app.jsx component which is the only component at the moment that we have in our application but generally this is going to be the root of our application and everything that we put inside of this component will be displayed next to our component we have this index.css file here I already imported all the fonts that we need and generated all the code that we need for our application as the purpose of this tutorial is not to learn CSS but to learn how to animate 3D models you can think of this file as a UI Library so all the classes already have been written for you and all you have to do is add the proper classes to the sections in your HTML file the next component is main.jsx file this is the main file where we are importing our app component our styles and we are rendering our app component inside of the root div and this div is located inside of the index.html file here so entire application is going to be generated here and you generate that using this create root method from react down apart from that we have this package.json file as well in case you are watching this tutorial years ahead and this repository doesn't exist here are all the dependencies that you need to install in order to make this project running let me just close this folder so that you can see entire urls like so and the dev dependencies as well now let's close this package.json file and the last file that we have here is veet.compic.jis file wheat is a front-end building tool and I use it over create react app because of its performance benefits all this file does is set up some configuration files for react but you don't have to worry about anything because it's going to do the configuration for you and it has better performance than the webpack so let's close this file and now let's install our packages to open the terminal I will just drag from the bottom in the vs code like so and I will choose here git Bash let me close the Powershell now run the npm install command and hit enter after couple of seconds you can see that we added this number of packages and here on the top we have this node underscore modules new folder generated for us which contains all the folder packages that we need for our project so let's close it now let's start our application by running the command npm run Dev let's face it for a couple of seconds we should start a development server for us and just open the URL from the console and as you can see our application is successfully running let me just zoom in a little bit so you can see it better and the other thing that you can notice is that some default Styles have already been applied to this application like background color and foreground color so this is a good start already the first thing that I want to build is the navigation on top so we want to replicate the apple style here so let's build this component first let me close this file and let's get back over to our Visual Studio code reduce the size of the terminal we don't need it and now let's create a new folder here inside of the source folder name this file as components or actually folder essentially all the components that we create for application are going to be stored here as we don't have multiple pages in our application we only have the components for this app.js file so let's add a new file and name this file as nav.jsx and this is short for navigation component let's import react from the top and I'm using Code snippet extension for faster development if you want to have exactly the same shortcuts as I'm building in this tutorial go to the extensions here and just install this simple react Snippets code extension now let's close it and let's generate new functional component so we can run the shortcut FFC for functional syntax component and now enter the name of the component for us it's nav without the e on the end so remove the e and we got generated this code snippet so what this code snipper does it generate a dysfunctional component with empty return statement and also export default on the bottom so let's start writing some jsx code first let's add an app here this now will have a class name of nav Dash wrapper next let's add additional div inside of this now and this day we'll have a class name and the class name is snap Dash content inside of this div we're gonna place our Northern list component with all the links for the navigation and we created this nav element for the semantic purposes and this tip is just for styling purposes is we need to apply some background color to our navigation and also to center it and apply some styles to our fonts as well so let's create an ordered list here in this list we'll also have a class name and the name of the class name is list Dash styled the first element of this list is going to be Apple logo so let's just review it for a second open the browser and if I open the final version you can see on navigation here on top on the left we have first logo and then we have all these links and on the right side we have here search icon and this like store purchase icon as well so let's build that let's get back to our nav.jsx file and let's import the logo first on top so type the following import logo from assets folder images logo Dot scg now let's add the list item here we don't need any classes for the list item and inside of the list item let's add the image so this image will hold the logo let's add the source property and passing the logo next we want to add the alt attribute as well and let's write Apple now let's run the default formatting so right click and format the document nice and let's save and preview but before we do that actually we need to include it inside of our app.jsx file so here in the import section write the following import now from components for slash nav and let's remove this hello text and place the nav self-causing component now let's save it and open the browser close this file and there you go you can see that we have this white background and our logo here on the left let me just zoom out a little bit because it's this is too much like so now let's add the links open an app.jsx again and close this app.jsx file now let's add additional list element or item and inside of this one we want to add anchor tag let's add a class name to this link the class name is going to be link Dash styled and we are not going to be adding the link attribute but on the real website obviously you want to add that as well for the first link the name is going to be store of this link so let's format this document let's save and let's preview at the moment the link is on the top right corner but when we add all the other links it's going to fall in place here next to the logo so let's add them so let's copy paste this link a couple of times because we're just going to be changing the name of the links the first one is store the second one is Mac the next one should be iPad then we have the iPhone next to iPhone we have watch now let's paste a couple more next to the watch we have airpods then we have TV and home next we have entertainment next to that we have accessories and after that let's paste another one and here let's place support okay okay and now we just need two more links the first one is going to be for the search icon so let's add an image element let's add a source attribute and let's add an alt for alt let's write search and let's import the search icon on the top here write the following import search from assets images search.svg like so and let's Import in the image here and let's do the same for the second link except that we're going to use the different image let's rename this one as store and let's rename the alt attribute as well and now let's import the store SPG as well copy the search import and just rename from search to store let's save this one again let's format this document and let's preview we got this failed import R so we are missing one letter here images and here as well images so let's save and let's preview again and now it works with this we have completed our navigation and let's proceed on building this Jumbotron so let's close this page and let me open Visual Studio code and now let's add a new file in the components folder name this file as geometron.jsx once again let's import the react on top and let's generate the functional component using the code Snippets name of this component is going to be Jumbotron and let's just add some placeholder text now let's import this component inside of the app component so on the top import Jumbotron from components forward slash Jumbotron and let's place it here next to the nav make it a self-closing tag now let's say this in preview for a second it's loaded correctly so we can continue let's close the app.jsx file and let's close the navigation as well now let's add some jsx code here I want to add a root div Dy will have a class name and the name of this class name is going to be Jumbotron Dash section and the second one is going to be wrapper the first thing that I want to create inside is the title so add h2 tag and let's add a class name of title the tact is going to be new below that you want to add another image here we're going to display iPhone 14 pro but actually we're going to use an image for it not the text and although this sounds like a weird solution but I probably wanted to keep the original look of the text on the logo which cannot be a hundred percent replicated with CSS or at least they wanted to be sure it's rendered correctly on all devices so let's add an image element and add a class name of logo Source we're going to add just in a second and let's add an ALT attribute right here iPhone 14 pro like so and let's import this image but here in the import section let's import iPhone from assets slash Images slash iPhone Dash 14. 14 Dot jpg and let's place this one and the source attribute here now let's preview that one and there you go let's proceed let's set a text below this image so add a paragraph and this paragraph also has a class name class name is text and the text is big and bigger which means that they have versions that are big and bigger below that let's set a span it will hold the description let's add a class name as well and the name of the class is description and the text is going to be just some paying options from 40 1.62 dollars per month for 24 months or 999 dollars before Trading we want to replicate exactly the same text as they have on their website let's see what we have for now and this big title looks beautiful with the gradient and apple is well known for the Simplicity and Aesthetics next below this we need to add a buy button and learn more so let's do that so here below this description let's add an ordered list and this unordered list has a class name name of the class name is going to be a links let's add a first list item and this one is going to have a button inside of it and here we're gonna say pi Also let's add a class name to this button and it's going to be simple button also we can add an href but actually we don't need it now let's copy paste this list item and for the second one we want to add an anchor tag this link is going to say learn more and let's add a class name link and let's save it now let's preview boom this looks beautiful let's continue and the last part is that we want to add an image on the bottom and we're going to have on the hand holding an iPhone so let's import image for that write the following import and name these images holding iPhone from assets we want to get into the images and the name of this image is iPhone Dash hand dot PNG and now let's add an image on the bottom here after the unordered list let's add an image now let's add a class name the class name is going to be iPhone Dash image source is going to be holding iPhone and let's add an ALT which is going to be iPhone let's see how it looks and boom this looks great later in this tutorial we're gonna add 3D model object here next to this phone so it's not going to look so empty and also when we add additional sections we want programmatically to scroll down to these sections clicking on learn more here so we're going to add that later now let's add those additional sections so let's get back here and in the components folder let's add additional file and name this file as sound section.jsx let me show you what we're going to be building in this section and when we open the final version you can see that on this second section you have more information about the sound and the new sound system that's why I call it sound section so let's build that again let's import react from the top and let's create functional component all using the code Snippets the name of this component is going to be sound section let's add a placeholder text here in the return statement and let's import this component in the app file so let's open the app.jsx and import on the top sound section and let's place it below the Jumbotron make this one a self-closing tag as well let's save the app and let's close both of these let's just preview it so that we are sure that is connected properly and there you go hello let's add some jsx code so let's remove this placeholder text let's add a div and this day will have a class name the name of the class name is sound Dash section and let's add a wrapper class as well inside a wrapper let's add one more div and this div will be a div with a class name of body and let's add additional div and this one will have a class name of sound section content and let's add additional class just content you may be wondering why we have so many divs but the purpose of them is to have the proper structure and to have proper Styles applied to them the first thing inside of the content is going to be the title so add an H2 element and this one is going to have a class name simply title and here we're gonna say new sound system like so and below that let's add a paragraph this paragraph has a class name text and the text is going to be feel the base like so below that we want to add a span with payment options and let's add a class name of description for the text I can copy from the final version so I don't have to type out here let me close the folders and let me format let's save and preview now the reason why you can't see anything on this section is because this section has opacity set to zero and later we'll use gsap to add a fading effect here so let's remove the opacity so we can see it actually let's open our index.css file and let's search for sound section and let's find the opacity zero and let's comment this out so now if we save it close this file close the folder and let's see again and there you go we just need to fix this typo and add a button and a link so let's do that here there's a typo should be filled and here after the description let's add an ordered list with the links let's add a class name of just links and let's add a first list item inside of this one we're gonna have a button similar like on the Jumbotron text will be just by and let's add a class name of button simple as that now let's add additional list item for the second one we're gonna have a link so error anchor element and let's add a class name of Link the text is going to be learn more now let's format the document and let's preview there you go this is the final version of this section except if you're gonna have iPhone here once we add our 3D object and this learn more button we're going to implement scrolling once we add the next section but since we added this section we can Implement actually this one so once we click on the learn more we want the page to scroll down to this section so let's do that so let's open the geometron component and here on the top let's add a function name this function handle learn more this is a fat Arrow function first we want to Target our sound section so use the document dot query selector and then let's target the sound Dash section and we want to store this inside of the constant named element we want to take the top position of this element and scroll down so let's use the window dot scroll to method this method takes an object as argument and this object receives a couple of parameters the first one is the top position and then we can use our element from the document query selector and call the get bounding client rect call this method this method will return the position and move on to access the top position and let's add an optional chaining operator which basically says if this element is undefined don't execute this function so this component doesn't get an error the next property is the left we want to set the Left To Zero as we don't need any horizontal scrolling and the last property is behavior which we're gonna set to smooth so that we have a smooth scrolling so let's use this method that we just created or write a function and here on the learn more let's add on click method and let's pass this function and now let's try this let's scroll up to the Jumbotron section and once we click on the learn more boom we get scroll down here and now let's build the last section of this website so if I go over to the final version and if you click on the learn more you can see that we got scroll down to This brilliant display section let's build that one so let's get back to the visual studio code let's close these files and let's add a new file in the components folder it's a new file and name this file as display selection Dot jsx again let's import the react using the code snippet and then let's generate new functional component this one is going to be called display section let's add placeholder text and let's Import in the app.jsx file so let's import it first import the space section from components slash display section and let's place it next to the sound section so just place the display section component and make it a self-going tag save this close the app.jsx file and let's preview there is no errors in the component we get the hello here on the bottom left and let's add all the components or actually the elements that we need let's remove this placeholder text and let's add a div this deal will have a class name of the display section and also let's add a wrapper class as well similar to other section let's add h2 tag and a class name of title the text is going to be new and below this text let's add a paragraph with a class name of text and here we're going to say brilliant with a DOT and let's add a span to the class name of description and let me copy paste the text as it's a little bit longer so let me open the final version and let me just copy this text okay let me close that and let paste the text here I will close the folder and let me format the document so it's more readable and below that let's add the button so again similar to other sections we want to have two buttons the first one is going to say try me and here we're going to have a class name of a button simply the second button is going to be called top and the class name is going to be back button the first button is gonna trigger the preview mode of your 3D model object and the second one is just going to be scroll back to top so let's save and see what we have so let's scroll down and once again this section is invisible because we have set opacity to zero and we're going to use the gcap to animate and fade in later so let's remove that opacity rule from the index file so open the index.css file and let's search for the display section and let's find the opacity and let's remove this just comment out now if we save this and close it we should get our text beautiful now we're just missing that 3D model which is actually the most interesting part of this tutorial we're going to be using webgi viewer to display this 3D model to our website which is powered by 3js and then we're going to be using the gsap to animate this model through the different sections of our website 3D model is already presented in a repository if you open the public folder you can find it here scene Dash black dot glb but in case you want to find some additionals or different models I will show you where you can find them there are plenty of websites with 3D models but I found my model here on the sketchfab.com and this is the model that we are going to be using in this tutorial as you may see this is iPhone 13 Pro Max but it will serve the purpose you can browse this website to find different models for example we can type here keyboard and then you you get a set of different 3D models and then when you find the one that you want you can just download them so as you can see here on the bottom you have download 3D model the format that we need is glb so just click on the download here and this model is free but you need to give attribution to the authors once you download the file you need to go over to this web GI website and the links to all the website are going to be in the description here we can open this online viewer for this 3D models just click on the latest version here and then we can open even newer version and just click on OK and now what we can do is we can just open up our 3D model and Import in the viewer here and there you go in this viewer there are a couple of things that might be very useful as you may see here we have this 3D reflection and on our website we don't have that because you want this object maybe to not have the ground or reflection so how you can remove it is just go to here to the scene and you have ground and you can just uncheck the visible and there you go also here you will be defining the initial position of the actual 3D model on your website how you do that is actually go here to the animations and you have camera views and then you can find the camera angle that you like and you can just click on ADD current View and it gets saved here then if you want a second view for example let's just rotate it like this maybe and click add current view now we can rotate to this views that you just saved so just focus on next and there you go so again this is very important so this is how it's going to appear on your website once you load this file once you set your initial the first position that you want you want to go here to the export and we have here assets export and glb Export because we're going to be using this glb file and also you want to click here on the drag or compress and you just click on the export glp we're not going to be exporting this file because we're going to use the iPhone that I have found and I also already optimized this asset for you guys so basically I just removed uh the ground so if I go to the scene I just remove the ground and I just compressed it also I added the initial the first position of the actual 3D model and additionally what's important is this position and this target values because these are the values that we are going to be animating or changing using the gsop library to rotate and animate our 3D model so let's do that so let's add a new component close this public folder and inside of the components let's add a new file a name of this file is going to be Fab GI V over .jsx now let's import react from the top and let's create new functional component and this one is going to be called web GI Uber and here in the return statement let's add a div and let's add an ID here it is going to be web GI Dash canvas Dash container and we're gonna use this ID to apply some styles to this container and inside of this div let's add a canvas let's add an ID and the idea is web GI canvas and let's add ref we're gonna render our 3D model inside of this canvas and we're going to use this ref as a reference so as a place where we can render the 3D model as well and for the ID we're going to use to apply some Styles so let's import graph on the top so import use ref from react if you're unfamiliar with user app hook all this hook does is it gets reference to an HTML element and then you can perform Dom manipulations using this reference so let's call this hook inside of our component so just call use ref and set the value as null this is the initial value and it will return in reference so we want to store that inside of the canvas graph this is the name of our reference and now we can use this reference and pass this to the ref parameter of our canvas and then we're going to be using this camera strap to initialize the 3D model and render it inside of this ref next the great thing about webgi is that they have a starter code for us so we actually start developing faster so if you click here on the get started here if you scroll a little bit down you have this web GI starter template on the GitHub so click on the that link and you get redirected to the GitHub webgi vanilla starter this is great but we cannot reuse this entire project because we are building this in react and this is vanilla starter project so we're just going to borrow some of the code so go to the source folder and go to the index.ts file first let's copy the Imports they have in this file so copy that and let's head over to webgi viewer and let's paste this and these are all the plugins that you use in the webgi viewer to apply some different effects and achieve some different styles so let's remove the ones that we are not going to be using we are not going to be using timeout we also don't need this diamond plugin let's remove this Frame fade plugin as well let's remove this one gltf animation plugin we don't even need this ground plugin either we need this bloom we don't need this temporal plugin we can remove this one as well we need this one and we can use this one as well for the rest of this one we can remove and let's add a couple of these that we're gonna actually be using in our application mobile and tablet checks so this one you're going to be using to check if you're on mobile or tablet so that we can optimize the position of our models now let's format this and let's add additional Imports once we are here so here let's add additional hooks that we're going to be using so we're gonna need use stat hook as well we're gonna use use callback you're going to need forward ref and use imperative handle as well for animating all of this we're gonna use gsap so import GSAT from gsap and let's import scroll trigger so import scroll trigger from gsap scroll trigger instead of all it needs to be scroll trigger like this now let's copy the setup function scroll a little bit down and here async function this function initialize the viewer so let's just copy it and adjust it to our needs for react here just copy and let's paste it inside of our function here let's first check what this code does we can see here that this is asynchronous function and on the next line we are initializing the viewer so we call the new viewer app method and we are saving that into the viewer constant and then we're passing the canvas argument and here they are using this document that get element by ID but actually we're going to use the camera strap that we just created so we can just replace that kind of strap.current next they are adding some basic plugins here using this add plugin method on the viewer and they're storing these values in the manager following that they are adding a pop-up here to show the download progress you can remove this one as we don't want this to be displayed next they are adding some base plugins using the viewer and once all the plugins have been added they are calling this viewer.render refresh pipeline so basically to load all the plugins and then below that they're adding the 3D model from the path let's update this for us it's going to be scene Dash black dot glb because we are writing this from the public folder and at the bottom they're adding some additional UI plugins these plugins would add an interface to your website like UI panel which you can use to update and modify your 3D model on the website but that's not what we want so let's remove that and since we're gonna have a lot of re-rendering on this component I want to Cache this function using the use callback hook this way it's not going to be recreated every single time that we re-render our component so let's remove that and let's call it use callback use callback hook Xbox an async function and at the end we provide the list of the dependencies when we want to recreate this function but it's going to be empty because we don't want to recreate this function now let's just copy the function that we already have here and replace the one inside of the use callback function or actually hook now let's format this document foreign actually we are missing the equal sign here and now we can format the document and let's preview but before we can preview we actually need to call this function and we can do that inside of a user effect look so in use effect we will just call this setup viewer function and we want to do this only once so pass an empty array of dependency lists now let's save this and let's preview so let's open the app.jsx file and let's import this component here in the import section type in import webgi viewer from components slash web GI viewer and let's display it here make it a soft close inside similar to others so let's save and let's open our website but actually see that we have an error so let's open up the console and inside of the console we have this canvas snip plug-in is not defined so probably we are missing the import let's go back and let's add it so here in the webgl viewer we are adding this plugin but we are probably not importing it so let's add it here in the import section let's save it and let's refresh and boom as you saw for a second let me just refresh it there you go this is our phone but now we need to adjust the animation so this is the initial position and also we need to clip the background because this one has a black background which is covering our navigation on top so let's do that here in webgi viewer let's scroll a little bit down after the import here of the manager so let's add viewer dot get plugin and the plugin that we need to do this is tone map plugin and we're going to set the configuration and the clip background is the property that we want to update we want to clip the background and set just to true and if we save this in preview you can see that now we see our background and actually background is transparent and we can see the navigation on top so now let's do a little bit of cleanup of this file because there is a lot of comments that we don't need and we can remove that and add the stuff that you need let's remove this comment here I will remove this one as well here and let's add some plugins that we have imported so we need this one GB buffer plugin let's uncomment all of these because we will need them as well we also need this Bloom plugin so adding these plugins to change the appearance of the 3D model and we're only including the ones that we need okay we are not adding the base plugins anymore because we are adding them individually and here we also need to remove this one because we are adding again the plugins individually I can remove this comment and let me see on the import section so we don't need any more add the base plugins and we don't need this canvas snipper plugin either this one we're going to be using later to determine whether we are on tablet mobile or desktop let's clean up a little bit more as well we don't need any of these comments and now let's add one more command so I want to disable the controls once we load our viewer so set the viewer scene DOT active camera dot set camera options so here we want to set the camera options and we want to use controls enable and I want to set it to false so what it means is we are disabling the controls so the users are not able to rotate the 3D model once the website is loaded next whenever we reload our website I want the position of our page to be on top so let's add window dot scroll to insert the top and left to zero so that we are always at the top position of our website and we can start with the animation now I want to add an event listener to the viewer itself what this listener will do once it's fired off it will update the position of the camera if update is needed so type the following viewer dot add event listener and the name of the listener is pre-frame once that fire off we want to execute this callback function and here we want to update our camera but in order to update our camera we actually need to get our active camera first so we do that here before all these plugins that you're adding here let's add new constant and here we will save our camera so we access the camera by viewer dot scene DOT active camera and using this camera we can access the position and the target so let's do that as well click once position equals the camera dot position and the target is const ant Target is equal to camera dot Target using these three properties that we just got from the camera and the viewer we're gonna modify and animate our 3D model because changing the view and the Target and the position of that you're actually getting that 3D rotation animation model so let's update the camera here and once this event listener has been fired off we want to call camera dot position Target updated and set that to true but we want only to update this in certain conditions so let's create a variable and name it as needs update and set it to just make sure that spelling is correct it's update and set that to true and we want to make a shack inside of the listener if it needs update then we want to update the camera position and set flag to defaults like so let's format the document and let's save and let's see if we have any errors so far and as you can see the background clip doesn't work anymore so let's fix that the issue is probably with the tone mapping plugin because it adds some stuff which disables the transparency so let's remove this argument and let's just add it true save that and let's preview again and this works correctly now so now what we want to do is once we click on the learn more we want this mobile to rotate and to set into this position here so let me just zoom out a little bit so it's at 100 and once we click on the learn more it will rotate and move on the right side here so let's do that we are going to be using gsap and we already imported the gsap and the scroll trigger plugin so let's register that plugin call the gsap .register plugged in and just pass in the name of the scroll because this is the animation that is going to be triggered on the scroll itself now I want to create new file where I will be saving this animation as I want to break down this file bit because it's becoming very large so add a new folder inside of the source folder and name this one as Loop which stands for Library and let's add a new file the name of this file is going to be scroll Dash animation.js first we will need gsap here as well so import gsap from gsap like so let's create a scroll animation function and Export it so type in export const scroll animation this is going to be a fat Arrow function and here we're going to receive some of the arguments so first we're going to receive the camera position then camera Target then we're going to receive on update we are going to be using this method to update the position of the camera every time we added the parameters of our camera we will call this method to update it and re-render so let's create a new timeline for the G sub so let's hit TL for timeline and let's execute the jsop.timeline function but before we add the animation let's first import this function inside of the webgi viewer and pass all the arguments that we need for the animation so that we can see what we are changing while we are coding the animation so let's import the function here on the top and make sure actually to save the file here first and then import animation from lib slash scroll animation and again as you don't want to re-render and recreate this animation function on every render let's use a callback to Cache it and memorize it so add a new variable const memorize scroll animation and we're going to use use callback again to memorize this function here we're going to receive position Target and on update and we're just gonna check if these three exist so if we have position and we have Target and we have on update then we want to call our our scroll animation function and pass all the all the three arguments here and we want to execute this only once so pass the empty array of the dependencies and now let's call this function here on the very end after the event listener let's call our function and now let's pass the arguments so first we want to pass the position this is the position of the camera and we Define it here we Define the position and the target of the camera so we are passing in the position and the Target and the last one is we need to create new own update method for updating our camera view so let's create it const on update this is a simple fed Arrow function and we just want to update this needs update here set it to true and we want to Mark the camera or actually the viewer as dirty so viewer dot set dirty this basically says that the camera and the viewer needs to be updated that's all it does and now let's pass this method here to the memoize scroll animation there you go and now let's go back to the scroll animation.js file and let's start with our animation here and now on the GSAT timeline we want to execute to function so this function takes the parameters of what we want to animate but first we want to animate the position of the camera and as a second argument it receives an object and inside of this object we want to define a trigger what will trigger the animation and the properties that we want to change for us in this animation when we are scrolling we are starting the animation so set the scroll trigger property and we Define here a new object inside of this object the first property that you want to Define is the actual trigger so this needs to be the element that is triggering this animation the element in the Dom itself for us this is the sound section so type in the sound section and where I found this class let me show you so if you go to our browser if we inspect developer tools you can see here they have this sound section and this is the second section here this one so we want this section to trigger the animation the next property is when we want to start the trigger so type in start and we want to start when the top of this section hits the bottom of the viewport so let me just show you what I mean by that let me close to browser console tools and here this is the top section of the sound system this right here this line and the bottom part of the viewport is this so this is static actually this Top Line is static it's always there but the bottom of the viewport is changing once we start scrolling so when we start scrolling it's changing and basically at this first scroll this is already reached the top and this is when we want to fire off our animation here also we need to Define what will end the animation so we set the end property when the top of the sounds section this reaches the top of the viewport so again let's review that top of the viewport is right here and the top of the sound section is right here so when these two meet we reached the end of the animation so if we scroll and when we reach this position position when the top of the viewport reaches the top of this sound section the animation should be ended and now if we update our position camera position and we'll leave it like that we will only have the start and end position and there will not be any transition in between so we need to use the scrub property you can set the scrub to true this way the 3D model will be changing its position from start to the end position using the scroll position so but if you want to add a little bit of delay you can add numbers here so I tried a couple of numbers and I found it too works the best if this animation is very heavy on our browser we need to do a little bit of implementation for the performance so we can pass in immediate render as false this means that you are not going to try to render this animation until it's actually triggered and once the animation is done we want to call this on update method and if you don't remember what this method does so let's go back here all this method does it sets this flag to true and says the viewer to set 30. so it means the viewer needs to be updated and then we trigger this event listener and then the camera position gets updated here and now we need to set the values that we are going to be changing so we have X y and z and where we get these values is from the webgi viewer so let's do that so we need to open the webgi viewer and then you need to import the 3D model that you're going to be using in your application to get the position of camera you need to go to the animations and then what you want to do is you want to position the 3D model the way you want it to look so you basically want to position the end position for your 3D model once you do that you can go and click here on ADD current View a new camera view has been added here in the list you can expand that and you can see that here we got the position of the camera and target of the camera so we have the x y z values and we can use these values to animate and add them to the gsap so this animation will have this position as end and once you add all the position that you want you can basically just go and keep rotating the animation that's all we want to do in our application to rotate the views that we saved in our glb file and retrieve this information and store them in the gsap animation function so let's do that I already tested the positions that I want for my mobile 3D model so let's just type them in the X position should be minus 3.38 the Y position should be -10.74 and the set should be minus 5.93 and now I want to execute exactly the same function but on the camera Target so we can reuse this code just add this function here and for the second one we want to remove the on update because it's enough to call this function only once and we want to update the element is Target here now let's update the values that we got for the Target for the X is going to be 1.52 40y we're going to set 0.77 and for the set let's add minus 1.08 and again I'm not coming up with these numbers randomly but I was playing around with the 3D model and I found that this position is a position that I want to have at the end of this animation so let's save this and let's try it out let's open the browser and if you click on the learn more boom we get our animation and if we scroll up the animation starts as well the problem is here that as you can see that this image is covering our 3D model so what we can do is we can change the opacity and Fade Out this all content I mean the other solution could be that we place the 3D model on top of this content but I would like to fade in anyways so let's do that again we can reuse the same function that we called so let me just copy paste this and now the target is going to be the jumble transaction so let's type in shambotron Dash section and here we don't want to update any positions but actually we want to fade out so set the opacity to zero like so the trigger will remain the same so let's try that and now if you scroll it's actually not working so let me check if the selector is correct so as you can see here we are missing o so it should be a Jumbotron section so if you go back and if we inspect this section so let me just show you can see that this is the the target CSS Target that we want to use okay let's try now we scroll now you can see that it's fading away and we get this nice effect but what we also want to do is we want to fade in this new sound system so this section should be fading as well so let's do that first let's open index.css file and let's find the not the space section but actually we want sound section sound Dash section and let's find here opacity so we want to set the initial opacity to be zero and as you can see here when we get to that position we don't see anything but now we want to fade in so let's add the fading animation so here we can reuse again the same code so just copy this function and paste and this time we want to trigger sound section content or actually we want to animate the sound section content and the trigger is again sound section here we want to set the opacity to 1. because we want to fade in there are rest of the animation should be remained the same so let's try now let's see and let's reload and click on learn more and there you go you see how it's animating once you start scrolling down here is semi-transparent and then we reach the final position it's fully fully solid great so let's continue now we want to add the last piece of the puzzle so once we click on the learn more here we want to get scroll to the bottom and we want to animate but as you can see we haven't implemented this scroll at all so let's go back to this field of Base sound system section and let's implement this first learn more and then we can animate this phone so let's do that let me close all these files and let's open the sound section here I want to add new function and let's name this function as const handle learn more and this is going to be fair Arrow function first we want to get a reference to the last section and we can store that inside of the element so Define const element and then using the document query selector we can Target the display section which is the last section so let me show you so right click and let's inspect and you can see this is the display section which is the last section of the website which we want to Target okay and now we want to scroll to that element so call the window dot scroll to and pass in an object with the parameters for the top we want to use the element and we want to get bound the client Direct and we want the bottom position we want to set the Left To Zero because we don't have any horizontal scroll and for the behavior you want to set this mode and let's use this method or actually function and pass it here to learn more so Define new event handler on click and just pass this function let's try it out so scroll a little bit up and let's click on the learn more and there you go beautiful now we should add the animation for this 3D model so let's open our lib scroll animation.js file and again we can reuse this uh this entire function so we actually can copy the both of this position because we're going to update the position and the target as well for the third animation first we need to update the trigger because we the trigger right now is the last section so display Dash section it's not the sound section anymore so the same for the last one and now let's just update the values so for x 1.56 for y 5.0 and for its set 0.01 and for the Target X is going to be minus 0.55 0.32 for y and for the set you want to set 0.0 like so let's save and let's see what we have if you click on the first learn more we get animation to the second section and if you click on the next learn more we get the animation for the last section beautiful and you see how easy it is to add this animation effect using gsap and 3js and you can also do the custom scrolling and you can see that the animation is changing while you're scrolling this is just outstanding the only thing that I want here is I want this section to fit in as well so let's add this animation we can actually reuse the animation from The Sound section so let's just copy that and let's add it here on the bottom here I just want to change the target for the last action it's going to be space section without the content here and let's update the trigger as well it is also display section like so let me save and let's see once again click on the learn more in here but actually we forgot to set the opacity initially to zero so let's find the display section if I can write it correctly and let's find it here so set the opacity to zero initially let's save it and let's try so let's refresh the page click on the learn more once again and there you go you have this nice animation fade in as you can see it's semi-transparent here and once we start scrolling it gets fully visible and solid beautiful the next thing that I want to do is I want to implement this try me to get that preview mode where you can play around with this 3D model and I want to implement this top so that we get scroll to the top of the page so let's first implement this topic because it's the easiest one let's first close all these files close all these files and let's open the display section here let's add another function and let's name this function as handle scroll to talk and this is going to be fat Arrow function again and all we want to do is to scroll to top so use the window Dot scroll to and we want to set the top to zero left to zero and set the behavior to smooth like so and now we can use this function and pass to this button so let's call the on click event and pass this function beautiful let's try it so if you click on top nice that's exactly what you wanted to do now let's implement this try me preview mode so what we need to do is we need to add on click eventually Center on this button and once we click on this button we want to fire our function from the pair component parent component is app.jsx file here and then inside of this function we want to fire off another function and that last function is going to be inside of this webgi viewer so let's start from that in order to reference a function from this component we need to use forward graph use hook so let's rename this function to use this hook so instead of the function let's write const we have gi viewer and we're going to use forward graph and forward graph takes two arguments the first one is the properties and the second one is the reference and we just need to wrap our component with this four draft hook so let's copy the component and let's place it in here and now what we need to do is we need to use use imperative handle hook so let's write here use imperative hand hook and inside of this hook we're gonna Define what is the function that we're going to trigger from the air component here we receive Fair Arrow function and the name of the function can be trigger preview and in order to enable this animation you basically need to have the reference to the camera to the Target to the position all these informations and this is inside of the setup user so we need to create another variable and store all of this inside of the variable so that we can access them inside of this trigger preview so let's add the reference to them we will use use statehope for that so let's create first one const viewer ref this is the name of our variable that we're going to use to store the viewer now let's set the setter function so set viewer graph and just use the use State hook to set the initial value to zero or actually to null let's copy paste this a couple of times because we're going to do the same for the Target so copy the target and here we want to set the set function as set-sided ref and then we want to update the third one which is for the camera and update the setter function should be set camera ref the next one is position ref position wrap and the setup function is set position Raw like so and now we can use these variables and use the gsap to change the position of our camera because as you can see on the last position this is the camera or actually 3D model position when you click on try me we want to change the position of this phone to face us and be a little bit smaller something like similar like here or actually on the first position something more similar like this position so that's what we are going to be doing so let's call the gsap .2 this is the function again and we are now changing the position route and we want to pass in X again x y that's it and values are going to be 4X 13. 04 or Y is going to be minus 2.01 and for the set it's going to be 2.29 and for the duration let's set it duration to two and at the end we want to call on update because we want to update the position once we set the values we actually want to re-render the camera view and 3D model so call the unupdate which receives a function as a callback and we want to set the viewer app to be dirty set dirty this means that we are marking the viewer for rendering and then let's call the camera ref position Target updated and set it to true so basically we're saying that the position of the target has been updated and we need to do the same for the Target so again let's call gsap.2 and this time we need Target ref and again position where X is going to be zero point one one where the Y is going to be 0.0 to the set is going to be 0.0 and set the duration to B2 just make sure to put the column in between and now we should be able to call this function from the parent so let me open the app.jsx and first we need to create a user ref reference to this function so use ref call this one and let's store that inside of the const webgi viewer rack foreign and now we can connect our reference to the component so use the ref property and I just pass the subject that we created like so and now let's define a new function that you'll be triggering from this display section let's name it can look preview it is going to be a fat Arrow function and we're going to access the method from the webgl viewer so X is the ref dot current and the name of the function that you define here is trigger preview like so and we are going to trigger this function from the display section so let's add another property and call it trigger preview and let's just pass the handle preview function now let's call this trigger preview property inside of the display section here and make sure to destructure it now let's add an event handler here on try me button so let's add on click and just call this function let's format the document let's save this one let's format this one and actually let's format this one as well let's save all of them and let's try and obviously we have an error so let's inspect to see what's happening and we have user app is not defined so let's import user so here in the app.jsx let's import loose wrap Hook from react let's save it and let's try now so in our our application is not broken anymore so let's write try me but it's not working for some reason so let me inspect let's see the console and you cannot read properties of null inside of the web Java viewer okay so that we are actually not storing these values viewer app Camera and position wrap and Charlie graph we only created these values but we never assign them so let's do that we forgot this step let's close this let's open the web Java viewer and here let's scroll a bit down here we are setting the viewer let's initialize and store it inside of our variable so set viewer ref and just pass in the viewer and now let's do the same for the camera so let's find where the camera is okay so it's here camera position and Target so let's call it set camera ref I'm passing the camera and we want to set position ref and press into position and set the target graph in crossing the target like so we are basically calling this set function and storing the reference to these variables so that we can use them inside of this trigger preview just for reminder okay let's try now let's scroll down and let's scroll to the end and now let's click on try me and there you go we have animated this 3D model iPhone to have this front facing position the next thing that I want to do is I want to enable this to be rotated and I want to hide all these things behind this this iPhone so let's do that let's open the app.jsx file and let's add a container here for all of these sections so we can hide them so let's add another div and let's add ideal content and let's add a reference to add a ref and let's make a new reference let's call it three smart as content ref and call the use refwork again so we're going to use this ref to hide all this content so pass the ref variable to this content and let's move in all these sections here so what we are going to do is just to fade away all these sections once we are in a preview mode and that's it and this webgl viewer will be only viewable on the website so let's do that let's pass this reference to the webgr viewer add new property and call this on content ref and just pass in the content graph here now let's open the web job viewer component now let's just access from the properties so call the props Dot contentrev set the current Style and opacity to zero like so so let's try that and now if we scroll to the bottom of the website and let's click on the try me we can see that all elements have disappeared apart from the 3D model now we want to be able to rotate this model but at the moment the pointer events are disabled for this section so if you go to the canvas you can see the pointer events are set to none so we want to fix this and to enable rotation so let's do that so let's add another reference to the container of the canvas let's store it inside of the constant and let's call this one canvas container and again we're going to use use refwork and the initial value is going to be null now we want to pass this to our canvas container so scroll down to the canvas and let's use the wrap and pass this reference here now we can use this to update it once we call the trigger preview so here let's call it and let's add the current dot style dot pointer events and equals to all this will remove the pointer events rule that we set earlier but what we also need to do is we want to set and enable a 3D model to be rotated so we do that here and set the viewer ref dot scene DOT active camera and set camera options we want to reset this back to controls enabled to true and this will enable the rotation of the 3D model so let's save it and let's preview let's scroll to the bottom of the page once again let's click try me and let's try to roll and there you go now we are able to control the 3D model how exciting is this you can zoom in zoom out change the position to whatever you want and inspect this 3D model this is outstanding but there is one problem we cannot exit this preview mode so we need to add another button here and once we click on the button we want to close this preview mode and return everything back to the normal so let's do that so we need to create another flag variable to be able to distinguish when we are in preview mode and we are not so Define const in the array preview mode and set preview mode you're gonna use the use that hook and set initial value to be false so at the beginning we are not in the preview mode and now when we call this trigger preview method or function rather we want to set this preview mode to be true so call the set preview mode and passing true and now depending on this model we want to show or hide the button that we're going to add here in the containers so let's add expression and let's see if the preview mode is true if it's true we want to render this button so add a button and this button will just say exit let's set a class name of Simply button like so let's save it and let's see what we got here so refresh the page let's scroll to the bottom of the page click on the try me and there you go now let's implement the exit so let's add a new on click event handler on the exit button so on click and we will create new function and let's call this function handle head is it like so and let's define it here so up to the hook here and we're going to use use callback because let's save it and we don't want to recreate this function all over again whenever we're rendering the component so we're calling this one as hand exit and we're going to use use callback hook and you're gonna receive this function inside of it and we're going to pass an array of dependencies later so what we want to do in this function is we want to reset the state that we set here in this trigger preview so we can reuse the code that we defined here let's copy this one and let's paste it here we want to set the pointer events back to none and we want to set the opacity of the content graph to 1 as well and also we want to disable here controls for the rotating the 3D model so let's reset them back set the controls enable to false let's also set the preview mode to false so that we hide the button and now we need to position our iPhone or 3D model back to its original position and we already defined its position inside of the leave scroll animation so we can reuse that code so you're going to find the Target and the opacity or actually this is for the display section so here the target and the position so let's copy this and let's paste it here called the gsap and call it to or actually we copied to Method as well let me just close the folders and let me format this and let's just update the position because here we are using the reference to the position and also let's update the target to ref and let's update this method on update method so we need to find that let's pass in a function and inside of this function we're going to call EUR and we're going to set 30. again something Simon that we already did and we want to call the camera ref and let's set the position Target updated to true like so and we want to update this function only with certain dependencies are updated so canvas container ref usition ref camera ref and Target draft and let's just not forget to call the GSAT on the second animation as well and we can close to the previous one perfect let's save this and let's preview let's open the browser let's scroll to the bottom of our page and let's click on try me now we are in preview mode so we can scroll play around or actually rotate and click on the exit and boom we are back at the initial position you can open the preview mode when we want zoom in play around do whatever we want and click on the exit and you're back excellent and the next thing that I want to do is optimize this for mobile devices so let's open the console tools so inspect and let's open up the simulator here on the right top let's refresh and as you can see this doesn't look correct so we want to update the positions of our preview model so let's do that we already are importing function to help us to determine this mobile intelligent check so let's add another flag which will be used to store the results of the mobile and tablet check so let's set up lag type in const is mobile and the setup function will be set is mobile and we're going to use u-state hook obviously to store the state and set to no first next in setup Uber here next reset your ref we want to call this function so mobile and double check and we want to store the result in a constant name this one is mobile or tablet like so and to be able to access this variable outside of this function we want to store that to our state variable so set is mobile as well to this constant so now we can access that through the entire functional component that we have here and now let's scroll a little bit down and here below this controls that we are disabling controls we want to check if is mobile or tablet if it is we want to reset the position and Target to fit the mobile phone so use the position to set to -16 point seven the second one is going to be 1.17 in the third one 11.7 again I was playing around with this with these positions and these values to set the one that corresponds to the resolution that I need for the mobile phone then we want to set the target as well set the first to zero for the X for y set the one point 30. 7 and the last one set to zero and we want to add additional class to our content draft so use the props Dot contentref dot current dot class name and set the class to mobile Dash or Dash tablet using this class we're going to hide the elements that we don't need on the mobile phone so let's save and see if this fixed our initial position and there you go it is but if you scroll down we can see that the second position and probably the third one are not working as expected so let's fix them so we want to pass this flag to memorize scroll animation as well so let's pass here is mobile or tablet like so yeah let's accept it here add it here it's a property or actually as an argument is mobile and we want to send it here as well so that we are able to update the positions okay and now we can open this inside of our scroll animation so let's save this let's format this document and let's open up the scroll animation here so we are receiving another argument here and we call it is mobile like so now let's update these values so let's use the ternary operator to make this more simple so let's just check is this not mobile if it's not Remain the values as they are if it is let's set the new value for the first X is going to be -7 now let's do the same for the add values for the second one if it's on mobile we want to set minus 12.2 like so for the third one we're gonna set minus 6.0 let's do the same for the Target here if it's not on mobile remain the same otherwise set to 0.7 for the Y let's set the value to be 1.9 and for the last one let's set it to be 0.7 okay let's save now let's update for the last section again we want to add this ternary operator and for the second one we're going to add nine point 50. we're actually 36 sorry for the Y we want to add a value of 10.95 if it's on mobile and for the set you want to set a position to be 0.09 on mobile and let's set the target for the display section as well here if you are on the mobile we want to set the position to be minus 1.62 then for the Y we want to set position to be 0.02 and for the last one we want to set position to be minus 0.06 let's save this and let's see what we got let's open the browser and let's refresh the page and if you click on the learn more we can see that we get the correct position for the second section and let's see in the last section great this looks awesome so what if we click on try me okay this looks a little bit different but if we click on the exit we can see that this value remained the same so let's update that one let's open the webgi viewer and we do that here in the handle exit function so again let's add again this ternary operator and let's check if it's not on mobile we're setting this value as it is but if it's on mobile you want to set 9.36 for the second one we're gonna set 10.95 for the last one is going to be 0.09 this is for the position and for the Target let's have it as well so we're gonna say minus 6.62 40 y let's set 0.02 and for the last Z let's set the value to be -0 point 0 6. like so let's save and let's format again actually we have this L we don't need that so let's remove the L and once again let's format and let's preview what we have and once again let's scroll to the bottom of our website let's click on try me this looks fine and let's click on the exit and boom we are back at the right position outstanding so let's scroll to the top and the last piece of the puzzle and the last piece of the website that I want to add is the loader because this animation is very very heavy on the performance of the website itself so we want to give some time the website and the assets to load in and display some nice animation for the user as well so they don't have to you know just see and wait and look at black so let's do that let's close all these files and let's add a new component in the component section so add a new file and name this file as loader.jsx let's import react on top and let's create functional component name it folder here we're just gonna import a gif image and display that so let's import animated logo from assets slash Images slash logo Dash animated dot GIF so this is already placed in the assets folder we just need it to load it and in the return statement let's add a div and this diff has a class name of loader and let's add an image let's add a class name of logo let's add a source animated logo and let's add an alt and set that one too iPhone loader or actually Apple maybe it's about because we have multiple devices on the loading animation so let's save this and let's import this inside of the app.jsx file let's import it in the import section here import order from components for slash loader and let's place it here and make it a self-closing tag let's save and see what we have now let's reload the page and boom we have this nice loading animation and after couple of seconds it fades away if you're wondering how this Fade Away animation is being done let me show you so let's open the index.css file and let's find this let's search for DASH loader class and as you can see I'm using the animation called Fade Out and this is just a simple CSS animation so we are fading from opacity 1 to opacity zero and we are holding this GIF for three seconds and after three seconds you're firing this animation which actually Fades away in 0.3 seconds and that's all it does and with that we completed our website now let's build and deploy this project so head over to our Visual Studio code and let's open up the terminal I want to open another terminal and let's actually open up a bash let's close the Powershell and let's close the first batch and now simply just run npm run build make sure to spell it correctly and this will build a static folder for us and we can use this folder to upload to the hosting and it's done that was very fast and as you can see we have this this folder and we can upload that so let me do that let's head over to the browser and let's open netlify.com website and you want to create account here everything is free so you don't have to worry about that go to the login and now let's add a new site here on the top right add a new site and we want to deploy manually or deploy actually so click here on the browse to upload and in the download section for me I want to click on the list folder so let's upload it click on the upload and let's wait for a couple of seconds depending on your connection and there you go it was very fast now what we can do is this is the URL of our application we can change that so go to the site settings and let's change the site name so we can type something as Apple iPhone website so that we have much nicer URL so let's save that and let's click on the site to preview it and it's beautiful it's working and there you go this is astonishing so let's sum up what we did and what we created so we created these beautiful animations which changes these three positions and at the end we created this preview mode as well which is astonishing really also we added this loading animation indicator at the beginning of our website and what we also did is we optimized this for mobile devices and obviously you could spend even more time to optimize this website for different devices right but that wasn't the purpose of this tutorial the purpose of this tutorial was to show you how to animate 3D objects inside of your website and there are some edge cases probably on this website that needs to be handled in regards to the layout and optimization I hope you guys learned something new and if you want to support me and get the full source code of this tutorial go check my patreon at patreon.com forward slash code with sloba or if this tutorial reaches 1000 views I will release the full source code on my GitHub also if you get stuck during the development of this project you can get my help so check the advanced tiers on my patreon as well also I have private one-on-one chat where I can help you and support you on this project until the next time happy coding
Info
Channel: freeCodeCamp.org
Views: 165,111
Rating: undefined out of 5
Keywords:
Id: IyBhFma4H1A
Channel Id: undefined
Length: 106min 19sec (6379 seconds)
Published: Mon Mar 27 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.