Three.js Tutorial Crash Course - 2021

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
3js is a javascript library that allows you to create 3d scenes directly in the browser ones that you can actually interact with and put html on top of to get to your next page so how do we go about creating a scene like this well we're going to need to do a few things the very first is we're going to need to install 3js and we're going to be doing so using a front-end framework called vitae we're going to need to create a scene a camera and a render three things we'll go over that are part of the 3.js framework we're going to need to create a plane and what i mean by plane is a plane geometry this entire square right here is considered a plane and 3js so we're going to need to be able to create that and then if we look really closely each individual vertice on this pane we need to make sure that it moves individually and then interacts with our mouse as we actually move it across the plane so you'll see right here we're going to need to add that hover effect i just mentioned we're also going to need to be able to modify this plane to our taste using something called dat.gui which is this interface up here basically if i go ahead and start editing this you'll see the plane in the background begins to edit as well this is super useful for debugging and making sure that you get the right look on your scene so that your end product looks exactly like you want it to and then finally we're going to need to be able to add html on top of this and make sure that it integrates with javascript so the html doesn't get in the way of our hover effect and then we can go to the next page when we click something like a view work button we're going to be covering all of that in this course right here but i'm also going to be creating a premium course that goes with this as well this is my portfolio site it's a very similar effect a little outdated using an old version of three js but nevertheless when i click on view the pieces right here you'll see that we have this nice little transition that goes and bolts into some stars we're going to be doing that as a premium course over on chriscourses.com but everything you see right here that i just went over in the very beginning we're going to be learning all that right here in this video for completely free so let's go ahead and begin to create this project well we're going to need a few files so the first thing i'm going to do is i'm going to open up my finder window and i'm going to go to a directory where i'd like to create my three.js projects so my home directory right here is christopher list simply my name and if i begin to scroll down there's going to be a folder in here called three this is one that i created specifically for any projects that relate to 3js so if you don't have this folder right now just go ahead and press command shift n if you're on mac and a new window will pop up you can name this whatever you want i recommend naming it three like i have right here if you're on windows just go ahead and right click in an empty area and click on create new folder and you should be able to create a folder called three so we have this folder called three i have another folder inside of it called three and that is just for the finished version of this so ignore that but we want to create a new folder this is going to be called my portfolio so if you see over here this text the super edgy text with my name on it and then some sort of description about me this is a example of a portfolio site it's about to introduce my work so people whether they be clients whether they be a job opportunity know what i am capable of in case i would like to pursue a job or a client so we're making a portfolio site essentially and this folder is called my portfolio my project makes sense so we have a directory for our project but now we need to open this up in a text editor of your choice so the text editor i like using is always going to be sublime text i know a lot of people like using vs code no matter which one you use you should be able to grab this directory and then drag it on top of your text editor and it should open up directly in your text editor as you'll see right here but now we need a few files we're going to need an index.html file which basically houses this whole project and then we're going to need a javascript file which houses all the code for the background scene so the first thing we want to create is some index.html if i want to test some html in the browser what i always like doing is just creating a simple h1 tag and inside of this just typing whatever text i think of hello is the first thing that comes to mind and if i go to file save with this text in here and you'll see the new tab open if i go to save i can now save this as a specific file where do i want to save this well within my three directory and then inside of the my portfolio directory we just created so this is going to be called index.html and make sure you add the html to end of this otherwise the browser won't recognize this as valid html even though we have html inside of it so we're going to go ahead and save this as index.html and once i do that you'll see my brackets light up meaning we have valid html inside of here so we want to make sure we save i'm going to hit command s right click this over in sublime text and then reveal in finder that's just going to open up our project exactly where we were and now what we can do is we can double click index.html and our html is in the browser so we know our file is being read which is perfect but now we need to import 3js well how do we do that you'll see over on the 3js website their installation page specifically there are a few ways to install 3js one of them is to install from npm which is package manager a little more difficult if you're new to javascript and the second is to install from a cdn and this is basically just copying in a url that contains the library code and just placing it inside of your project so you might think that this is probably the easiest way to do it but let's go ahead and install it this way and see what happens so we're going to install from a cdn basically a url that pulls in all the 3js code what i'm going to do is i'm just going to copy these script tags i'm going to go back over to sublime text in our project and right at the bottom of this i'm just going to paste in the script tag so theoretically we should be able to use all the content within this url right here let's go ahead and see what content is within this url first if i go ahead and copy this url paste it in the browser and try visiting it you're going to see cannot find package 3 at version that is because 3js expects you to add a version to this url before you can actually pull it in so i'm going to type 0.126.1 which is the latest release as of the time of this recording and if i hit enter you'll see this is all the code that 3js consists of it's a huge file but this is everything we need to create 3d scenes in the browser so we want to make sure we're pulling this into our project we can copy the url right here go back to sublime text and make sure we are replacing this version that just has the version inside of the carriage we want to go ahead and replace this url with the one that specifies that we want to use version 126.1 so now on save if we go back to index.html and refresh nothing happening well let's go ahead and check out our console we can check out our console by right-clicking and clicking inspect if i look inside of our console and refresh still not getting anything just yet but if i go on over here to our code and then console log out the scene that we are creating with 3js and then refresh in our browser you'll see that we're actually cause logging it out so we successfully imported 3js we can actually write all of our code directly here within the script module now typically i like having all my javascript in a separate file because it makes things a little cleaner for when i want to bounce between what's html and what is actually javascript what is in the 3d environment so what we're going to do is we're going to create a new file by going to file new file it's going to open up a new file over here in sublime text and this is going to be where all of our javascript goes so we want to make sure that we are saving this as simply index.js that is going to be our main javascript file so we hit save we now have a javascript file in place if we go back to index.html we want to make sure that we are taking this javascript code over here going inside of index.js pasting it in and then we need to make sure that we are referencing index.js from our html file so to reference this we can add in a source attribute and we want to make sure we're going inside of our my portfolio directory which we have right here and that we are referencing index.js or javascript file so save refresh in our browser and you're going to notice something we are getting an error access to script at this url from origin null has been blocked by core's policy now cross origin request is a whole nother beast that's probably its own tutorial in itself but basically what's happening here is since i'm trying to pull in this package directly from a separate index.js file rather than within the script tags from index.html we're getting this error we can't actually pull in the scene that we want from 3js now a quick and easy way to fix this is to set up a local server right now we're simply running the html file in the browser but if we set up a web server something that's there for the purpose of serving up web files to the browser this error is going to go away and you're going to see that shortly so what is the quickest way to set up a front-end web server well in my opinion it's using a framework called vite vitae is essentially a front-end server created by the same guy who made vue.js and whenever you save a file within the server it's going to automatically update your page with all of your new code so it's super helpful when you're developing you don't have to save go back and refresh this is going to refresh everything automatically so this is what we're going to be using for our server to make sure we don't get that weird course error whenever we are importing 3js so how do we install vitae well we're going to open up a new tab and we're going to visit vitaejs.dev we're going to click the get started button and we're going to start scrolling down and right here where it says scaffolding your first vitae project this is what's going to help us create a vt project so we want to use what is called npm node package manager if you're unfamiliar with it basically it's a node.js app that allows you to download external packages from other authors such as 3js vitae vue.js you can install all of those using npm and the useful thing about downloading packages with npm is you're always going to have a list of all the packages that you're using within your project and what versions they are so that if another developer were to come in and use your project they'll know exactly what the project is using so two things here one is vitae requires node.js version 12 or over and two we need to make sure that we run this directly within our terminal with npm so you also need npm installed well what happens if i don't have either of those if you don't have node or npm or your node version is under 12 what you want to do is just type in node.js the very first result is going to be the node.js official website you can go ahead and click the download option right here and then you want to find the installer of your choice whether or not you're on windows or mac i'm on mac so i would click this one and it's just going to download this package that will allow me to install nodejs specifically version 14.16. you'll see if i were to go through this whole thing i would install that version directly i already have it installed so i'm not going to go through but if you don't have it installed make sure you are installing it with the windows or mac installer and once you get through all of those props you should have node.js installed in your system the correct version because this is version 14.16 as of this date and also whenever you install node.js you also by default install npm so npm should work for you by default as soon as you install node.js as well so once you have node installed let's also install vitae because we now have npm as well so to run this command we're going to need to open up a terminal window well how do we open up terminal on mac we're just going to click this little magnifying glass right here spotlight search and type in terminal you're going to see we get the terminal result we're going to click it and it's going to open up a new window this is the project currently running in the background so i can show you guys but for you guys it should open up a new window and yours is going to look white mine only looks black because i have a little bit of customization put in here it's going to start you off directly on the home directory right here which is a little squiggly but before i continue for you windows users out there you're not going to be opening up terminal you're going to be opening up something called powershell it's basically the windows equivalent to what we have right here and it's pretty easy to navigate for the most part maybe not as nice in my opinion but it'll still get you going where you need to go and you should be able to input these commands as well so we're starting off at our home directory which is notified by the squiggly and if i ls which means to list the contents of this directory you'll notice our home directory is one to one with our home directory over here in the finder if i start scrolling down to the visible folders you'll see all of these match up with what we have in the terminal which is pretty cool so we want to make sure in the terminal that we're going inside of the current project we're working on so let's do this the easy way by finding it in finder first we're going to scroll down to three and inside of here is our my portfolio project so if i want to go to this directory directly within my terminal what i can do is type in cd which stands for change directory and i want to change directory into my portfolio so i'm just going to grab this directly from finder drop it into the terminal and it's going to give me the exact pathing i need to go to in order to dive into this within terminal so if i cd directly into this and hit enter you'll now see we are inside of my portfolio we can list out the results of this folder and you'll see we have index.html index.js this is perfect this is exactly where we want to run npm init vitae.js app so we're going to go ahead and copy this and remember make sure you have a node version over 12 and that you have npm installed which comes with node so just make sure you have node we're going to run this command and hit enter so what is the name of our project well it's not a vitae project it's going to be my portfolio it's going to give you a little prompts that we need to select what kind of javascript do we want to use do we want to use any template associated with this vitae project well for our purposes we want to focus on just 3js we don't need any of this other stuff right now so we're going to select vanilla which is just basic javascript and that's all we need to do so if i go back to finder we're going to see what that command just did we don't see anything here just yet but if i click my portfolio well we just scaffolded a whole new directory called my portfolio and inside of here are going to be a few files that vitae just created for us so we can set up that front-end web server so we have two instances of my portfolio but really we want to use the one that we just created so i'm going to do is our initial my portfolio i'm going to call it dash old i'm going to drag the new vt my portfolio into our route 3 directory and then i want to make sure that i am cd inside of that vitae my portfolio so here in terminal i can type in cd just drag my folder on over here hit enter and now i'm just going to follow the commands that we see right here outputted by vitae specifically these bottom two npm install and npm run dev so if i copy these and paste hit enter we're going to see a few commands taking place npm install what does that do well if we go ahead and open up my portfolio and sublime text which you might need to do again since this is a new vt project if i look inside of package.json npm install is going to install all the dependencies listed out within this file and their specific versions so npm install just installed vitae version 2.1.0 because it is listed out as a dev dependency within this file and then when i run npm run dev while it's telling terminal to run this command right here so we're running a vitae command it's basically just an alias or another word that says run this command so all we're doing when we run npm install is installing vitae and then we are running it when we run npm run dev which you see right here so when those commands run you're going to see that we are now presented with a vitae dev server is running at localhost 3001 for my instance for you it's probably 3000 i just have another server running in the background but now what we can do is we go back to our project you'll see here we're just opening up the file in the browser if i go ahead and open up a new tab and then paste in localhost 3001 which was presented to us over here and hit enter while we now have a vitae app in place and like i said the very cool thing about vitae is if we go ahead and start editing some of the contents within our project now such as going into main.js you'll see that this is where we are rendering out hello vitae in the documentation on the page if i begin editing this to something else edit edit and hit save watch what happens no manual refresh required everything is just instant so it's going to be very helpful for when we are working with on this 3js project so let's get back to the focus of 3.js get all this weird server npm stuff out of the way for the time being if we go back to finder and open up our old my portfolio project and sublime text again go back to index.html you'll see that we were importing index.js which just wasn't working for us before but if i go ahead and copy the contents of this and paste them into our vitae app we can get rid of everything that we see right here and then i hit save and open up my console in the browser you'll see that our scene is now showing as expected once more so now we can have a separate javascript file that loads 3js without that chorus issue taking place so now if we go back to our to do we can go ahead and check off install 3js using vitae perfect so the very next thing we want to do is create a scene we want to create a camera and then we also want to create a render these are all things that are required to get some sort of interface on the screen so we already have a scene in place if you look right here with the default boilerplate code provided by 3js we are creating a new 3 scene and we are storing it inside of a scene constant so we created one of the three things that we need we have a scene but now we also need to create a camera so to create a camera i'm going to create a constant called camera this is going to be equal to a new three perspective camera and a perspective camera takes four arguments the very first one is going to be the field of view which is a value in degrees so it's kind of like whether or not you would like your camera to be a wide-angle lens which shows a lot of the scene altogether or whether or not you'd like it to be a telephoto lens which only shows a small portion of the screen so the degrees we want to put in here for our field of view is going to be 75 that should show a ample amount of screen this is the default 3gs usually uses so we're just going to go with that the second argument for perspective camera is going to be the aspect ratio of our scene so if we look back at our initial project you'll see that our scene takes up the entire width and the entire height of our browser window so the aspect ratio that i want is going to be our windows enter width divided by our windows enter height and that is going to give us the exact ratio we need so that when this camera is looking for objects on the scene it's going to know to size them to the correct dimensions relative to our browser window specifically its inner width and its inner height the next two arguments are going to be clipping planes what is a clipping plane well a near clipping plane which is the third argument is going to state how close does an object need to be to the camera before it actually gets clipped out of the scene altogether clipped out of the scene just means it doesn't show on the scene you're going to this is all going to make a lot more sense as we go through it these two aren't that important to explain right now so for the near clipping plane we're going to be putting point one and for the far clipping plane we're going to be putting a thousand so we can see all the objects from a distance of point one from the camera very close all the way down to a thousand units out there and are seen in three dimensions anything past a thousand we're not going to be able to see so we have our camera but what do we need next well now we need a render something to combine the scene and camera together to put something in three dimensions on the screen so to create a render we're going to create a new constant called render and this is going to be equal to a new 3 dot web gl renderer object and now just to make sure that these are all instantiated correctly what we can do is we can console log each one out individually so we already have our scene we'll go ahead and console log out our camera as well we'll console.log out our render too and we don't even have to refresh because vitae does it for us automatically and you'll see each of these was created successfully because we see their individual objects being outputted in the console if you're not seeing this over here in the console right now just double check your code and syntax to make sure you have four arguments within a perspective camera object and that you are typing out webgl render correctly over here when you create the renderer so we have these three objects but we're not seeing anything on the screen just yet because all we're doing is storing these within constants we actually need to make use of them now so our render is basically a canvas html element that runs webgl which is basically the framework that's required to run 3d on the web so what we need to do is we need to put this canvas object directly within our html and to do that we're going to be using javascript we're going to be injecting it into our html so to inject it into our html we can select our document object specifically our body which if we look in our elements tab over here we're going to be injecting it directly within this body tag we want to append a child element what child element we want to append well our renders dom element and just by doing that you'll see over here we now have a black box and this is what's going to be representing our scene where we can edit 3d objects if i go ahead and inspect this you'll see we just appended in a canvas object and this canvas object is what's going to be running webgl which allows us to run 3d stuff in the browser so cool now one issue we have here is obviously this canvas element isn't the full width and height of the browser so what we can do is before we append our renderer's dom element we can go ahead and select a render and use a set size function to say what size should our render element actually be before we append it onto the browser well the first argument here is going to be the width we want this element to be so what width do we want we want the windows enter width and if you're wondering where this variable is coming from well this is the exact same thing as window.enter width the thing is whenever you're referencing the window object within your code you don't actually need the window object if you reference a property directly from the window object it's going to know what you're talking about automatically so therefore we can use inner width and inner height by their cells it just makes our code a little cleaner so our width is going to be equal to the inner width of our browser and then our height is going to be equal to the inner height of our browser the full width and height so now if i save you'll see now it's taking up pretty much the full width and height but we still have some padding up here where's this padding coming from if i go ahead and inspect our page and look at our body element you're going to notice by default it has a margin of 8 pixels every website you create the browser is automatically going to be adding on 8 pixels to the margin of your body element if you don't specify otherwise so we don't want this margin there at all what we can do is go to index.html and within our head tags we're going to be creating a style tag and this is where we can add some css to take away this default margin so what i can do is i can select our body element by typing in body and then what css do i want to alter well simply it's margin and instead of a pixels i want this to be equal to zero we don't want any margin at all so if i save this we get an auto refresh and that margin goes away and now i can't really scroll to the left or right there are no scroll bars in place which means that our 3.js canvas is indeed taking up the full width and height of the browser so that will take care of that so if we go back to our to-do list we created a scene we created a camera and a render and now we actually put our render on the screen and this is going to be acting as a canvas in which we inject 3d objects onto this we can interact with them in a 3d space so technically we can go ahead and check off create a scene camera and render from our to-do list but now we need to actually get some sort of geometry some sort of mesh within this screen so we can start interacting with it so the very next step we're going to do is create a plane but to make this as easy on you guys as possible i'm going to start with the most basic object which is actually going to be a box so whenever you want to put some sort of element within your 3gs scene you're going to need two things one is going to be you need a geometry a geometry is basically the wireframe of your object it contains data relating to all of that objects vertices which actually start piecing together the object such as a box so we'll have vertices here here here here here here has data related to all those vertices that connects them into a box shape the second thing we need is a material the material is what goes on top of this geometry to actually fill in everything in between vertices are just points that really create some sort of wireframe but to fill in that wire frame we need some sort of material in place which is basically just painting up the faces of the box so if you have a geometry and you have a material together you can create a mesh which you can then put into your 3gs scene and it'll render correctly which you'll see very shortly so to create a box geometry what we're going to do is we're going to create a new constant we're just going to call this box geometry makes sense this is going to be equal to a new 3 dot box geom tree make sure your casing is correct over here so this takes three arguments specifically for the box geometry 3.js has a lot of different geometries that you can go ahead and use within your project box geometry is just the most simple one to start with if you'd like the full list of which ones you can use you can simply head over to the 3js docs and there it will give you a comprehensive list of all the geometries you can actually use but let's focus on box geometry what arguments does a box geometry take well it takes a width it takes a length and then it takes a height so the three things we actually need to build a box in 3d space so the width of our box we're going to declare as one unit you kind of think of this as feet i'm not sure what the exact units are actually within 3gs but we'll go ahead and say that this is going to be one foot for the width one foot for the length and then we're going to use one foot for the height so if i save this and then console.log this out just to make sure that we instantiated this correctly go over to our console you're going to see now we have a box geometry object and if i look inside of this specifically within this attributes property one side of here is going to be all the data related to our vertices everything that is actually required to get this on our screen why are we still not seeing anything even with all this data related to a box and its vertices well simply because we don't see anything until we create a mesh which remember requires a geometry object and also requires a material object so that's going to be the second thing we create is a material object so go ahead and say const material is equal to a new 3 dot mesh basic material and this takes an argument of an object and inside this object we can specify a color and this color is in hexadecimal value so if i want to go ahead and create a color of green to start that's pretty basic what i'll do is i'll type a0x to declare we want a hexadecimal value in here and then i can write out that exact hexadecimal so 0 0 means our red value is going to be 0 out of 255 if you're used to using rgb values the second two numbers here are going to declare how green should this object be if i want these to be as green as possible well we don't want to use 0 we want to go all the way up the hexadecimal scale from 0 to 9 to a to f which is going to be the brightest version of that color so our green value here is set to the brightest color it can be and then our blue value which is the last two numbers is going to be nothing at all and if you don't want any value there for that kind of color you just add in zero zero so we save it's going to refresh first automatically but now we want to console log out our material and it looks like our material was created successfully so now that we have a geometry we also have a material we can use the two in tandem together to create a mesh so i'll create a constant called mesh and this is going to be equal to a new three mesh and what arguments does a three mesh take well simply a geometry and then a material so we want to make sure we're using box geometry here our material is already called material and if we console log out mesh now we have a mesh successfully created so looking good shape but how do we finally get this mesh into our render well we want to take our scene object and then call its add function this is what's going to add meshes into our scene what mesh do we want to add well the box mesh that we just created now still not seeing anything even when adding the mesh to our scene and that is simply because although we put our render within our html over in the browser we're not actually calling any render function which is going to render out our scene and actually render out all the objects on our scene well we need to call our render and call its render function which takes two things it's going to be the scene we want to render out and then the camera we want to use to be able to actually navigate and move around in our scene you'll notice we didn't actually use camera anywhere just yet this is where it's going to come in handy to actually display what we want to show directly within the scene so if we go ahead and select our camera constant copy it and then paste it into this render function down here it's being called off of our render and hit save so i'm not seeing anything i know it's probably getting frustrating at this point but it's there now i promise how do we actually see the box that we just created well we want to select our camera and we want to select its position property specifically where it is on the z-axis so going forward or backwards and we want to make sure that it's not located in the center because everything by default is going to be spawned in the center unless you specify otherwise so we're basically going to be moving our camera from the center of the screen where our box is also spawned we're going to be moving it backwards so we can actually see what's right in front of it so if we set it equal to 5 feet 5 units within 3.js and hit save finally going to see our box although it kind of just looks like a square at the moment to start seeing this in 3d what i want to do is add in some animation so to create animation we're going to be doing exactly what we do within our canvas games if you've ever watched any of those tutorials we're going to be creating a function called animate and inside of here we're going to be calling windows request animation frame function which in return calls another function so what we're doing here is if we were to call animate it's going to run request animation frame which in return calls an animate function which is declared right here which just means it's going to run the code again and it's basically just going to put us into this loop specifically so we can start animating values as we need to as we begin coding our project but in order to activate this animate function at the very bottom we need to actually call it so it begins the loop if i call animate not going to see anything just yet but if we go ahead and put render inside of this animate loop so we're calling render over and over and over again and select our mesh specifically it's rotation start with the x-axis and start adding on one over time as animate begins to call itself we hit save you're going to see that it's spinning very very quickly along the x-axis so it's probably spinning i believe ford at the moment let's go ahead and slow this down instead of increasing by one we're going to increase by 0.01 and you'll see that spins a lot more smoothly let's go ahead and add on some rotation to our y-axis as well and now you'll see the full 3d object in here as a cube as it begins to spin so right off the bat when we're looking at this you'll know it's a little jagged on the edges if it's looking jagged for you guys as well it's probably due to the device monitor you're using so right now i'm on a macbook pro which has a retina display and when i try rendering out this web gl by default it creates a little bit of jagginess along with the actual rendering to fix this where we have our renderer created and where we are setting its size right after we set the size what we can do is select our render and call set pixel ratio and this is going to be equal to our window object which we don't need to actually specify it's going to be equal to our devices pixel ratio device pixel ratio so if i go ahead and save this it's going to refresh automatically you're going to see the jaggedness is reduced significantly because we're telling 3gs what the ratio of pixels are on our device from width and height and it's going to make sure that it renders things clearly just because it knows that additional data so we have a simple box on the screen but if we go back to our piece over here we don't want a box we actually need a plane just a nice flat square or rectangle so how do we go about putting a plane within our project rather than just this simple box well let's go ahead and focus over here the first thing i'm going to do is start deleting out our console logs so we can go ahead and focus on the code at hand so i'll delete these ones these ones and these ones since everything is working we know that and we don't really need those additional consoles right now so a new mesh even if it's a plain mesh requires two things well it's going to be a geometry and a material but this is just going to be a different kind of geometry so you might be thinking can we just copy line 18 and instead of box geometry can't we call this just plain geometry and then set it equal to a plane geometry object well yes technically this is how we are going to be doing things but what we don't know here is what arguments does a plane geometry object take so if you don't know what arguments a certain geometry or material takes the best thing to do is go to the docs so i'm going to show you guys how to use the docs within 3gs to create this plain piece for when you're creating new objects yourself so what you want to do is open up a new window and you're just going to type in three js docs and go ahead and full screen this we're going to click the very first result this is on 3js.org and then we can go ahead and start scrolling down on the left hand side to see what is actually available to us so when you're looking for what geometry you want to use what kind of shape do you want to create you want to scroll down to the geometry section you'll see right here we have an option for box geometry which we just used we just created a box but we used a more simple material than what you're seeing right here you'll see this code looks exactly the same to what we just put in or at least close to the same but we want to use a plane geometry so we'll go ahead and scroll down we see plane geometry is here underneath the geometry section we'll click it scroll down this is what a plane looks like this is indeed what we want to create that background effect and now we can look at the code example to see how this is made so it looks like it takes three arguments well what do these three arguments actually mean if we go down to the constructor we can see what they mean exactly the first argument right here is the width this is equal to a float data type a float data type is just a decimal number basically what is the second argument it takes well it takes a height also a float a decimal and then it takes width segments and height segments so how many segments should be put in between the full width and height of the plane you'll see right here it looks like we have two so let's go ahead and create our own plane geometry using this plane geometry constructor example so we know that we need to put in a width let's go ahead and start with a width of five units we'll also start with a height of five units as well so we have a perfect square here with segments it doesn't really matter what we put here since we're not using any segments just yet we'll go ahead and start with 10 and we'll also specify our height segment which is an integer so a whole number should also be 10. we have our plane geometry we can go ahead and console log it out to make sure that it was created successfully go back to our project refresh and it looks like indeed it was created successfully so now we need some sort of material in place we can just go ahead and use the same material that we created for our box geometry but we're actually going to assign it a different color just so things don't blend together as we begin to test this so i put this beneath plane geometry i'm going to call this plane material and then i'm going to specify our color for this should be red instead of green so i'll get rid of the brightness values on the green value over here put those to zero zero the first two numbers here are going to be the brightness values for red if i turn those up to f which is the brightest value we're going to have a red plane material and whenever we have a geometry and material ready to go well we can go ahead and call this new 3 mesh code so we want to create a new 3 mesh that uses our plane geometry and that also uses our plane material and we want to set this equal to our plane mesh and whenever you have a mesh ready to go all you need to do is add it to the scene with scene add plain mesh and now you'll see our plane mesh was added to the scene successfully and if you actually want to see this move in 3d what you can do is you can select your mesh within your animate loop so plain mesh and start adding on to one of its values such as rotation dot x add on point zero one you'll see now our plane is flipping albeit very fast that's a little better both of these spawn right in the center so you can kind of get an idea of where these are located and what they look like as things begin to flip now you'll notice as our plane begins to rotate well the other side of it just isn't visible at all and this is my intention by the 3.js authors they want to make sure your scene is as performant as possible so when you get to the other side of a plane it's just not visible by default but we can make sure that it is by declaring a property within our plane material so we declared its color but we can also declare a side property and set it equal to a three dot double side both d and s should be upper case here and if we do this you'll see both sides of the plane are now visible this is probably what we want to stick with while we develop just so we don't get confused as we begin to move around our scene whether we go under the plane or over the plane we want to make sure that we can see both things here so we have our plane in place this box geometry isn't really serving a purpose anymore and now that we kind of got our hands wet with geometry and materials so what i'm going to do is i'm going to remove it from the scene altogether let me just go ahead and delete the box geometry the material the mesh and then the scene.add where we actually add the box mesh and then we also want to make sure that we are deleting the mesh rotation down here which is forcing it to turn and twist in those directions so if i remove all of those now we just have our plane we don't want our plane continuously rotating like we see right now so i'm just going to go ahead and comment out this code and now we basically just have a square that doesn't really have any dimension associated with it so one thing we can do here is we can begin giving this a new type of material one that actually interacts with light so that when we begin moving the segments of our square in different directions we're going to be able to see all the little segments associated with our plane right now they're all flat we can't see anything especially because we're using the mesh basic material object which doesn't react to light so if i want this to be able to react to light i'm going to use a new type of material specifically i'm going to use a mesh thong material this can take the same arguments that we have within our mesh basic material if i save this we're just getting pitch black compared to the red we saw before this is because in order to view this material mesh following material we need to make sure that we have a light on the scene something to actually illuminate it so the next thing we need to add to our project our scene is going to be a light let's go ahead and do that now if i create a constant called light and set it equal to a new three direction null light this is going to take two arguments one the color of the light and two the intensity of the light so for the color of our light we can specify a hexadecimal value which remember we do by declaring a zero x going to make sure it's in that hexadecimal format and then what is the actual color and hexadecimal value well i just want this light to be a pure white so i'm going to make sure that we add in six f's to declare rgb should all be as bright as possible which when combined creates a white color the second argument here is going to be the intensity of this light i want it to be as bright as possible or at least as bright as 3.js allows so i'm going to be setting it to 1 and not seeing anything yet because remember whenever we create a 3 object we need to make sure that we position it correctly and that we actually add it to our scene so that it's rendered with everything else so to position this i'm going to select our light constant select its position and then i'm going to call a quick set function so what does a set function take well it takes three arguments x y and z where do we want to put this relative to the center of where it is placed right now the center of our scene so i don't want to move it left or right so i'm going to select 0 for the x i don't want to move it up or down at least not yet so i'm going to put 0 for that as well but i do know i want to move it towards me because if i look right in front of me that is where the plane is actually placed by default so if i move that light back from our plane basically putting the light right in front of it by putting a z value to one and then i add the light to our scene you're going to see we have our light shining directly on our plane this looks a little different than our mesh material you'll see right here we have a little bit of different color taking place here compared to everything just being the same value of red it's a little lighter in the middle than it is on the edges of our plane which is perfect for when we need to start editing the vertices to create that jagged like effect we see over here within the example so in order to add the jaggedness we're going to want to be dealing with our plane mesh object so what i'm going to do here is i'm going to console out our plane mesh and see what's inside of it if i console logs out i can open up our mesh object start looking around at all the properties that a mesh actually consists of we're going to want to focus on our geometry object which is actually the plane geometry that we created earlier but this is what we're going to be editing to make sure that we get that mountain like jacket effect inside of our attributes property within the geometry property we're going to have another property called position and this position property contains all the data related to each of our vertices within this plane geometry specifically within this array so if i go ahead and open up this array let's focus on the first three values with an index of zero one and two so these guys right here these three values when used together represent one vertices within our plane so if i look at the value negative 2.5 that is going to be the value for this vertices x position so where is this vertices of the plane on the x-axis from left to right while negative 2.5 is probably going to be somewhere along the left-hand edge of the actual plane the second value right here 2.5 is going to be the y-coordinate of the vertices so where is 2.5 was going to be somewhere up here along the top of our plane and finally this last one of the trio is going to represent the z value of this vertex which is going to be zero because our plane doesn't actually have any depth if we look at the third value for every single index in here it's always going to be zero simply because a plane has no depth it's saying that the vertex's position on the z-axis should be equal to zero within our scene space so our vertices are stored in this group of three formats specifically because it is better for performance when running them within the browser it does make things a little harder to edit since we want to make sure we're editing these values to alter our vertices move them around a bit but to preserve performance this is better than putting these in their own individual properties such as an x position a y position and a z position it just wouldn't be as efficient otherwise so basically what we need to do here is to create some sort of jagged effect we need to start editing each individual vertices positions within this array so the very first thing we're going to do is we're going to select this specific array so we're constantly logging out our plane mesh starting right here if we start diving into this we want to get our geometry so dot geometry and then we want to get the attributes so go ahead and select attributes like so we'll go ahead and go in a little deeper we want to select our position the position of each individual vertices within this plane and then we want to go into our array which has all the values where our vertices are located so dot array if i save this we get that array specifically and now we can begin editing the values inside of it to affect our piece over here so to edit these values in groups of three i'm going to use a for loop i'm going to declare a let called i set it equal to zero and then i'm going to specify how many times do i want to loop through this well i want to loop through this for as many items we have within this array over here which is 363. if i go ahead and replace array length with our array and then call length on top of that array we're basically saying we want to go through this for loop 363 times now just looking at our for loop right now this is kind of messy just because this value right here is so long makes our for loop a little hard to read so something that we can do is we can take this cut it out of there cut it out of our for loop and we're going to create a constant and we're going to use two curly brackets one opening one closing and put inside of here array what we're going to do is set it equal to that value that we just cut pasted out right here and we are going to delete the last portion of this dot array.length so this is called object destructuring what we're doing is we are still selecting the position attribute of our geometry object but we are creating a new constant called array that references that position attributes array directly so this right here is essentially getting transferred to this small constant over here and by doing that we can use the small constant within our for loop and reference its length like so so we're still getting the length of our position array we're just doing it in a cleaner manner within our for loop by using a little bit of object destructuring so this should still loop 363 times if i go ahead and console log out i you'll see that we are still going through this 363 times we're just not seeing 363 because this count to zero as one but this is working exactly like we would like it to so if we start console logging out our array values which we are going to access using this i lut we declared up here we can select our array and say we want to const lock out each value within it by placing i inside of here you'll see all those are outputted into the console so these first three values are related to one vertices let's say we only want to loop through the vertices each little individual vertices related to our plane rather than each of the values associated with that vertices such as x y z we don't want to luther all that but just each individual vertices so these three together what we can do is instead of adding one onto i we can add on three instead so now we're only looping through every three values compared to every value within this array and to make this a little easier to understand we can start setting these values equal to their xyz counterparts using constants so i'm going to create a constant called x and that's going to be the very first value within our array very first value within our array is going to be equal to 0 which is what i is equal to so x technically should be equal to negative 2.5 then i'm going to create a constant called y this is going to be equal to the second value within the array so when i is equal to 0 we know we get the first value but if we add 1 onto i well we're going to get the second value which is going to be equal to 2.5 and then finally we have our z which is going to be the third value within the array that is going to be equal to zero and once we run through this first iteration well we're going to be adding three onto i so if i let's just say hypothetically is equal to three well now if we put three inside of here we're going to be selecting the fourth option within our right which is going to be negative point two we add one onto three that is going to be four so we're getting two point five and then finally if we add two onto three well that is going to be index number five so if we count zero one two three four five we're going to get zero for that so this combination of x y z right here is going to be equal to the x y z position of each individual vertices so using these xyz positions what we can do is we can start altering these positions to start randomizing the geometry of our plane so if i want to begin editing the x position of each of these individual vertices what i want to do is i want to select our actual x position which is going to be reference from this array with a value of i not x exactly because this is going to be a new value that doesn't actually alter the original we want to make sure that we are setting array i equal to array i or x here we're going to be using x because it makes a little more sense logic wise and we want to add on some sort of value so let's say we want to move all the x vertices to the right by something like three units you're going to see pretty much everything was moved to the right except for the very first vertices over here now why wasn't that vertices moved well simply because while i was explaining this we changed i to three which means when we're editing the vertices in this loop we're skipping over the indices 0 1 2 which is going to be that very first vertex we want to make sure we set i to zero so we make sure we select it and now everything was translated to the right we want to make sure that we're translating it to the left we can just go ahead and subtract three now everything on the x is moved by three but we want each individual vertices to have some sort of randomness associated with it especially on the z-axis because on the z-axis that's what's going to make things really bulge out within the shape that we have right here so let's go ahead and start with z to go ahead and set the z position of one of our vertices we're going to go ahead and add two onto i right here because that is going to give us the third data value within our array and we don't want to use the current x position we want to use the current to z position and start altering its value so if we go ahead and add three onto z it's just going to look a little bigger because we're moving it closer towards us but what if we add a randomized value here instead of three what if i go ahead and add on math dot random any value zero to one well things are starting to look pretty crazy here once we save that but we can't really see any of the depth of the inner vertices you'll see that it's just still all flat well why is that by default that is just the way a mesh following material interacts with light so if you want to see all the little individual faces within this plane using a mesh fong material what we can do is we can add on a flat shading property and set it equal to a3 i'm sure that's all uppercase flat shading property and if i save this you'll see that our plane is basically magically transformed into this nice geometrical object so going back to our loop if i comment this out you're going to see we still get a flat plane but when we start altering all the z coordinates and we have this flat shading turned on we can see all the depth associated with those z position translations so now when we go back to our to-do list we can successfully check off creating a plane this is great for the basics obviously we're not completely there just yet but we're moving in the right direction so the next thing i want to do is be able to modify this plane to the exact dimensions that we would like until we get something that we're happy with now in our code we could do this simply by changing the dimensions within our plane geometry instantiation so here we can go ahead and change the width to something like 10 the height to something like 10 save and refresh and you're going to see it is quite bigger and we can keep toying with these value until we get something that we like the only issue with this is it's kind of slow we're going to have to keep going back and forth changing values over and over again and it's just not as efficient as it could be if we were to use something called that dot gui so if we look at the example this little control panel right here is known as that gui it's a graphical user interface to change different things within your screen here i've set it up to manage a few properties the width of our plane the length of our plane how many segments are within this plane both on the width and height section and then i believe this controls the hover color yes it looks like it does i can turn this down it changes to a different color when we hover over it so see dat.gui makes this really easy to edit and get to the exact dimensions that we would like to use within our actual piece rather than having to play around with all these different values by hand within our code so how do we begin using that.gui within main.js well one way to do it is you could go inside index.html and pull it in through a cdn link within a script tags source attribute but if we want to do things a little more professionally we'll actually install that.gui through npm similar to what we did with vitae so to install dat.gui into our project using npm we can open up our terminal again i'm going to open up a new terminal tab and you'll see inside of here i'm already within our project directory you'll see this is indeed our vitae my portfolio project and here is where i want to run npm install and then the package name we want to install which is going to be dat d a t dot gui gui and then i want to put dash dash save at the end of that and when i put the dash dash save at the end and hit enter you're going to notice inside of package.json dat.gui is now listed out as a dependency so we can say our project depends on this one library to work technically this could be listed as a dev dependency because it's something that will probably only show in development anyways but for this instance it doesn't really matter where you put it whether it be dev dependency or dependency we just want to make sure that it's in our project and downloaded so after installing dat.gui now you can use it within your project so if i go over to main.js i can scroll to the very top of this and similar to what we did with 3gs installing that into our project so we can use it we are going to import the whole library of dats.gui as dat from and then what is the package name well if we look within package.json the package name is that dot gui so we can copy this go back to main.js and say we want to import that from that dot gui we can test this by console logging out that going back to our vitae app and if i refresh you're going to see we have a module here if i open it well it looks like we have some gui functions and methods inside of here so we successfully imported that.gui using npm so we're on the right path here so to start using dat.gui we need to start adding in little individual properties sections to start altering everything within our app so the very first thing i'm going to do is i'm going to create a gui object i'm basically going to instantiate that so i'm going to say a const of gui is equal to a new dat dot gui all uppercase object and we want to make sure that this is working as well so what i'm going to do is i'm just going to console.log this out always make sure your code works as you go about it and here you'll see we now have a gui object so now that we have a gui object what we can do is we can call gui dot add and the first argument here is going to be another object and this object is going to contain all the properties we actually want to start editing within our actual 3jsps so in order to put an object here we need to create one right below this constant gui i'm going to create a new object called world this is going to be equal to an empty object to start but we need to think what kind of properties do we want to start editing within our world well we want data related to our plane let's go ahead and add a plane object in here set it equal to an empty one to start as well now let's think what kind of properties does our plane have well if we look back to our plane instantiation we know our plane has a width it has a height it has a width segment and it has a height segments attribute associated with it so let's start off with just the width of our plane we know our plane has a width and to start we're declaring it equal to 10 so our default value for width is going to be equal to 10 and now that we have this object available to us we can insert it within our gui dot add function so first argument here is going to be an object we want to select our world and specifically our plane object now what property within this plane object do we want to have a slider associated with well that is going to be our width property this is going to be equal to a string width so now just by saving with this you'll see that we have a number selector up here that we can start changing the value of but let's say we want this to be an actual slider not just a number of value well the third argument is going to be the minimum value you want the slider to be able to go to so what is the minimum width our plane should have probably no less than one and what is the maximum value our width should have this is going to be the fourth argument that gui dot add takes uh we don't really know just yet how large we can go let's go ahead and just say 500 is going to be the max of our slider and now you'll see our width by default is 10. up here when we refresh it's equal to 10 by default and we can start altering this value with a slider because we inserted this one and this 500 as the third and fourth arguments within gui dot add so as i begin changing this the value changes for our world plane width so this value is changing but now we need to actually integrate it with our code so that when this changes we are basically recreating our geometry with this new value so our plane geometry is only instantiated only called once and that is on load because it's not inside any event listener or any function that would actually call it so what we can do is we could say whenever we change the value of width within our world dot plane we want to regenerate this geometry so at the very end of gui.ad i'm going to change on a function called on change and this is going to have one argument it's going to be an arrow function a callback function so that whenever this value changes we're going to be calling this function we can see this in action by consolidating out our world plane width and now whenever we change the width up here we should be able to see it be changed within the console so if i begin to change things you'll see that that value is indeed changed as i begin to move the slider up and down so we know we're creating a plain mesh but when we change the value of our gui slider we want to select this plane mesh and specifically we want to select its geometry so let's go ahead and console log this out to make sure that we are getting this correctly put it inside of console.log we get rid of the second console on we don't need that anymore save it's going to refresh we begin altering our slider and you're going to see we are indeed selecting our plane geometry but what we want to do is we want to set this plane mesh geometry equal to something new that takes into account the new width of the world plane that we have going on with our gui slider so the very first thing we want to do is we want to select our plane mesh geometry which are already doing and we want to dispose of it this is just going to get rid of it from the scene altogether get rid of from the mesh and then the second thing we want to do is assign it a new geometry so what geometry do we want to assign it well we can go ahead and grab our plane geometry instantiation right here paste it into our onchange callback and we're going to say plane mesh dot geometry is equal to this new 3-plane geometry but we don't want to set our plane geometry equal to a static value with a width of 10 we want to make sure that we're setting this equal to the value we are getting from world plane width so instead we can put in here world plane width we save and then we begin to edit our value and you'll see our plane begins to change as we edit its width now as i go bigger and bigger it just goes off the screen completely not something we really want it kind of makes all the values above it looks like 20 a little useless so what i'm going to do is i'm going to change our slider max to 20 and now this gives us a little more breathing room to get different values with the slider directly looking pretty good but you'll notice as i decrease and increase the width it did away with all of our vertices manipulation that we just worked so hard to get and it only comes back on refresh so although we're creating a new plane mesh geometry with a new width something we are not doing with this new geometry is setting the new positioning of all the individual vertices we need to make sure we do this again whenever we assign a new geometry to our plane mesh so where are we altering all of our vertices if we scroll down it's going to be this for loop right here so we can go ahead and copy this go to our on change function and just paste it in there and let's watch what happens now when we change our slider value you'll see it gets smaller and smaller but all the vertices are still being edited in real time as we begin to change and all we're really doing here is setting the z position of each vertice to be something random each time this width value actually changes so looking pretty cool and this is giving us the ability to get the exact value we might want within our plane object but we might not want to tailor just a width we might also want to tailor the height as well so a quick challenge i want to challenge you guys to add the hype property to this dat.gui instance pause the video do so now otherwise let's keep going so to change the height with that gui pretty simple thing we can do here is we can just go ahead and copy gui dot add create a second instance of it so we know we want to change a property related to our plane object well we don't want to alter a width property we want to alter a height property this is also going to be equal to 10 by default because that's what we have it to at the moment and now we can change width to height we can keep our height value equal to 1 to 20 and that seems reasonable we're going to dispose of our geometry and set it equal to our dag gui width but also our world plane height that's pretty much all we need to do to affect the height of our plane let's watch what happens i begin to decrease the height while the height of our plane gets smaller and smaller increase it gets bigger same thing for width both of these are going to work in 10 but you might have just noticed a bug even though my height was set to 4 as i begin to change the width well the height goes back to something larger why is that well you'll see right here where we are changing width with our slider we're creating a plane geometry set to the new width that we have up here but we're still setting it equal to 10 which was the initial default value we need to make sure we are setting it equal to the dynamic value we're setting within world plane height so we can simply change this equal to world plane height save and now decrease our height decrease our width everything stays relative to each other which is exactly what we want now looking at this this code right here is quite duplicative i don't think there's actually any difference between our on change callback functions within height and also width so if you have a large portion of code that's exactly the same that's a pretty good indicator that you should probably abstract it and put it in its own function so we're going to do exactly that what i'm going to do is i'm just going to copy all this code right here that generates a new geometry for our plane and sets its vertices and i'm going to create a new function called generate plane and inside of here i'm going to call all the same code so now instead of using this empty arrow function right here i'm going to call generateplane whenever we change our height and things still work exactly the same now we can delete all the code with our on change for our width get rid of the empty arrow function put in generate plane just like we did for our height and now our width is edited just like our height is and they work in tandem together because they both use the same function the function edits the plane geometry based on the world plane width it also edits the plane geometry based on the world plane height so let's go ahead and finish this off for not just width and height but also width segments and height segments for our plane so we can get more geometry put in there in case we want it so we know this value right here the third argument within plane geometry is our plane's width segment so we'll know that we'll want to basically edit our world plane with segment and this fourth argument right here 10 that is going to be equal to not our width segments for our plane but our height segments instead now these two properties don't exist just yet so we're going to add them into our plane object up here by default we set our width segments equal to 10 and we also did the same thing for our height segments that also is going to be equal to 10. so finally we need a way to alter these what we're going to do is copy gui dot add and say that we want to be able to alter our width segments property and then we want to be able to alter our height segments property as well any value 1 to 20 so we save that we now get the two extra sliders and if we begin changing these you'll notice the amount of segments begins to decrease as we begin to decrease its value and same thing goes for height segments if we go all the way down for to one for both of these we're just going to get basically a plane square with no segments inside of it but if we go all the way up to 20 for both of these we get something that's really really geometrized i don't know the right word for something that has way more polygons compared to the amount that we had before and we can definitely increase this value by a little bit let's go ahead and increase both the max values for these by 50 increases we get something that just looks really wild which we can always reset if we just refresh the page so looking at our to-do list we now know how to modify our plane with that dot gui so we're going to check this off as well now before we go on to hover effect there's one more thing i want to include in here you might have noticed within the original project over on this side that i can actually select a portion of the screen and if i start dragging while i'm selecting it you'll notice that the scene changes its orientation along with me this is what's called orbit controls within 3js and i want to show you guys how to add that to your project as well especially as you begin to alter your scene over here using that dot gui so one thing i'm going to include in this is add orbit controls let's go ahead and do that now adding orbit controls is actually relatively simple but the thing is they don't compare with the 3.js library by default that we're already importing this is actually something we're going to have to import separately but thankfully we can import it using a very similar url compared to what we have right here with unpackage and 3js so what we're going to want to do is we want to take this first portion of the url everything from https up to 3 add to 0.126.1 we're going to copy this and then we're going to try to visit it within the browser to make sure we are referencing the correct file so we want to paste that in there if we visit this right now well we are presented with some sort of version of 3js but we want just the orbit controls because those come separately from 3js to get the orbit controls from this url that we just pasted 3 at 0.261 at the very end of this we're going to want to paste in or type the following url so if i full screen this you'll see that this is slash examples slash jsm slash controls slash orbit controls so basically we're going into the whole 3js repo that also contains examples within this examples folder well we're going into an importable module called orbit controls if i go ahead and visit this well this is all the code related to the orbit controls object so now we know this is the correct url to pull from so we can go ahead and copy this and then right below where we are importing three we want to import specifically orbit controls object from that exact url so if we save then console.log out orbit controls like so visit our app over here we refresh well looks like this function right here is everything we need to create orbit controls within our scene to begin moving around and to instantiate orbit controls all we need to do is include what camera do we want to be able to move around our scene and then what is the dom element of our render so below where we created our camera and also our render we'll go ahead and do this right here where we're currently altering our cameras position z we want to create a new orbit controls object and the first argument here is going to be the camera you want to use so it's going to be our perspective camera we are creating above and then we want to select our renders dom element so we'll put that as the second argument we save and now when we begin to click and drag on our scene you'll notice that it moves around a three-dimensional space and as i begin to move this around you'll notice even if i go to the back side we're not seeing anything over there even though we definitely turn on the double side rendering now why isn't anything showing it's simply because our light is only facing forward on this side of the screen as we begin to move our camera to the other side of the mesh you need to realize we're only moving the camera we're not rotating the plane at all but since we rotate the camera to the back side there's no light over there so we don't actually see the back side of our plane even though technically it is right in front of us so if you're wondering why you don't see anything on the other side it's simply because there's no light over there you can create a new light and push it to behind our plane and let's go ahead and do that now just to show you how this works if we want to create a new light we can simply copy these three lines of code that creates a light positions it and adds it into our scene this will be back light we're going to set our backlight's position to have a value of z negative one and then we're going to add our backlight to the scene so if we save this and then start going to our backside now with that new backlight we're going to see the back side of our plane simply because it's lit up so if you're wondering why it's not there you just need to make sure you add a light because of the material we're using only works if you have some sort of light on top of it so now you are more than free to start editing your plane as needed while moving around your scene to ensure you get the exact look that you would like so if we go back to our to do we now successfully added in orbit controls so only a few more things to do we need to add in our hover effect and then add in html let's get the hard one out of the way by adding in the hover effect so when we're adding in a hover effect it's useful to have some sort of pseudo code in place to know exactly what steps we need to take in order to get there so i wrote a few out and the very first thing we need to do is add some sort of mouse event listener so that whenever we move our mouse on the screen we are tracking its coordinates we want to use this coordinate source c knows where exactly is our mouse relative to the objects on it so one piece at a time let's go ahead and start with adding in a mousemove event listener and then we're going to do something called normalizing mouse coordinate so going back to our code whenever i add in an event listener i typically like doing it at the bottom of my code because that way i know this is where all of my events are at least events related to the window so to add in an event listener i'm going to type add event listener which takes a string for the first argument this is going to be the event you want to listen for i want to listen for a mouse move whenever our mouse moves across the browser window and what happens whenever we move our mouse well whatever is inside of this callback function the console log out something such as move so we begin to move our mouse you're going to see that it's logged out on the bottom left-hand corner of our console so we're going to need to be able to grab the x and y coordinates from this event to get those coordinates we can select our event object which is always going to be passed through as the first argument within this callback function so if i console.log out event dot client x we're going to get the exposition of our mouse as it moves across the browser window you'll see now if i go far to the left mouse is equal to zero if i go far to the right it's equal to about 640 which is what this browser width is set to if i want the y coordinate all i have to do is change client x to client y save refresh now the higher i go to the top the closer we get to zero and the further down i go the larger this number gets so we know we want to use client x and client y outside of this mouse move function so what i'm going to do is i'm going to create a mouse object mouse is going to be equal to an empty object with an x it's going to be equal to undefined to start an x coordinate and then a y coordinate which is also going to be equal to undefined these aren't going to be defined until we actually move our mouse across the screen so here we can say our mouse x is equal to event dot client x wherever it is on the screen whenever we move the mouse and then our mouse y is going to be equal to event dot client y save and then we console log out mouse and start moving you'll see now we're getting the coordinates for both x and y no matter where our mouse is on screen the closer we get to the top left hand corner the closer we are to zero now the issue with this is if we want to use a raycaster well the raycaster uses what's known as normalized coordinates the coordinates we're using right now are not normalized because the center of the axis is the top left hand corner of the screen which is the default for browsers and websites but the default for 3gs the center of the screen is right in the middle of the screen so whenever our mouse is in the center over here x and y need to be equal to zero so that the right caster is actually positioned correctly to understand where our mouse is pointing relative to the plane we have on the screen so basically we need a way so that the further we move from the center of our screen to the left we get a value of x is equal to negative one as we begin moving to the right we should be getting a value of one so we need to change our coordinate system from negative one to one within our mouse move function so to start what i'm going to do is i'm going to divide client x by our windows inner width let's go ahead and see what we get with that if i begin moving further to the right-hand side of the screen it looks like this might actually work the further and further i go to the right you'll see x is getting closer and closer to one which is a good normalized coordinate from zero to the right-hand side of the screen but as i start to going to the left as we get to the center well this should actually be equal to zero for the x-coordinate not so much 0.5 and the further left i go we need to make sure that the left hand side is equal to negative 1 not something near zero so to save you guys some headache and the math you need to do for this what we can do here is we can put this inside of parentheses multiply it by two and then subtract one and that is going to give us normalized coordinates for the x value you'll see as i begin going near the center x is equal to zero as i begin going to the left x is equal to negative one and the further i go to the right x is equal to one so that's exactly what we need to start interacting with our mesh and three-day space but we also need to do the same thing for client y so you might think we can simply take this code right here and paste it in and set mouse y equal to it while changing client x to client y and enter width to enter height you might think this works let's go ahead and watch what happens to our y value as i begin to go down you'll see that y is getting closer to one and you might think well isn't that what's supposed to happen isn't supposed to get closer to one as you go down within the coordinate system of 3gs the further you go down on the y-axis the more negative your number should be getting so we shouldn't have a positive number for y as we go downwards we should actually have a negative number same thing for when we go upwards y should be equal to something positive here instead so all i need to do here is instead of subtracting one we're going to add one and the value of client y divided by inner height we're going to set this equal to negative to basically reverse the direction in which our y coordinate is being red so if i save that and we start going down from the center of our y axis you're going to see our y values getting closer and closer to negative one which is perfect and as we go closer towards the top it's getting closer to one so now we have normalized mouse coordinates that we can use within our 3js scene but we now need to use something called a raycaster let's look at our to-do list real quick we added in the event listener we normalized mouse coordinates let's go ahead and import that raycaster so luckily for us we don't have to import anything separate here like we did for orbit controls all we have to do here is import the raycaster directly from the 3gs library so where we are importing our scene camera etc i'm going to create a const called rightcaster this is going to be equal to a new 3 raycaster so we can always console.log this out to make sure it's working safe way to do things there it is we imported the correct object now let's go ahead and use this to test where our mouse is relative to the objects on the screen but first what is a ray caster whenever i think of raycaster i always think of a little laser pointer that's always being pointed from wherever our mouse is on the screen directly into the 3d space a raycaster is just an object that tells us where our little laser pointer dot is relative to the scene so if i move my mouse off of our object over here our raycaster is pointing its laser pointer over there therefore it's saying our dot isn't touching anything if i move it on top of our plane over here well our dot is touching the plane so the raycaster object is going to say red alert our laser pointer is touching something and it's going to be able to monitor touches for pretty much anything that we have on the scene we only have one object right now this is all it's going to monitor but if we had multiple objects the raycaster has the ability to monitor whether or not it touches those objects as well so within our animate function this is where we want to check whether or not our red caster is intersecting with our plane so we're going to select our raycaster and we're going to call it's set from camera function and this takes two arguments one it takes our mouse our normalized mouse coordinates which we already took care of within our event listener and two it takes a camera as a second argument so if we save this you'll see we're getting an error cannot access mouse before initialization this is simply because we declared the mouse constant beneath the function we're using it at so we just need to make sure that we are declaring it in a position above animate which if we move it up there you'll see we don't have that issue anymore and we still get our mouse coordinates being logged as so so now that our raycast or our laser pointer is being pointed from wherever our camera is pointed towards since we use this set from camera function what we can do is we can call raycaster dot enter sect object what object we want to test whether or not our laser pointer is touching well that is going to be our plane mesh we're going to store this in a constant called intersects so now if i cause log out intersects you're going to see it's equal to an empty array but as i begin to move our mouse you'll see our coordinates are being logged but if i begin to move over our plane you're going to see we're logging out some sort of object within this array and if we look a little deeper inside of here well it just so happens that this object is our plane mesh so to make this a little more clear let's go ahead and delete this console.log mouse within our event listener refresh put our mouse over here so nothing is intersected just yet but if i begin to move over our plane you'll see now it is tracking that we are indeed mouse over it and the cool thing is since this is set from camera if we begin to move our camera well the scene is automatically going to take that into account if i start moving my mouse up here where the plane would have been beforehand we're not tracking any intersection just now but as i begin to move my mouse onto the plane you'll see we r d tracking it if i move it off well it's no longer there so that is how you're going to start tracking whether or not your mouse is over certain geometries within your scene and to create a conditional in our code for this what we can do is we can say if intersects dot length is greater than zero we could say that we are intersecting we start moving we're intersecting we go off we're no longer intersecting and so forth so this is where the code is going to go that changes the color of our plane as we begin to move our mouse over it so looking at our to-do list we imported our raycaster and we tested for intersex sex so based off the intersected face now all we need to do is change the surrounding vertex colors now when we hover over our plane we want to make sure that we're changing the colors of the faces that we hover over so we have a way to test the hovering but now we need to actually change the colors of the vertex and it creates this nice little spotlight effect over your mouse as you begin to move across the plane what we're really doing here is we're changing each individual vertex color which actually spreads out and creates that nice spotlight effect rather than changing each individual face so how do we go about doing that well let's go ahead and go back to our project and we're going to want to focus on one of the attributes related to our plane so back where our plane geometry is being created we have two places in which this is being created in one is going to be within this generate plane function and if we look a little further we're also by default creating a plane geometry whenever we load the page so if we scroll a little bit further down within this load code you'll see here we're already altering one of the attributes related to our play mesh geometry and the attribute is position well let's go ahead and catch log out our plane mesh geometry attributes and see what's available inside of there if we go ahead and console.log this out this is going to be our plain mesh attributes and we look inside while we have three attributes available to us we have a normal a position and a uv now normals and uvs those are a whole another topic we don't need them for this video but position is obviously where is the vertices in the 3d scene for the x y and z coordinate now these are the three attributes that come with the geometry by default but there is one that doesn't come with it by default but actually one that we can add in into this attribute object and that attribute is going to be a color attribute so if we want to add a new attribute into our geometry well the first thing we need to do is select that geometry so we can reference our plane mesh geometry we'll go ahead and paste it below and then we want to call a function called set attribute the first argument for this function is going to be what attribute name do we want to set well we already have one for normal position and uv this one we want to set is going to be color and what is an attribute within a geometry well we can kind of get an idea for this by looking at the current attributes well they are going to be a float 32 buffer attribute which if we actually look inside of one of these it's basically an object full of all the data related to this array and this array for position specifically contains all the data for the vertices positioning they're just in groups of threes which we went over a little earlier so the second argument we want to put in here is what kind of attribute are we creating well we're going to be creating a float32 buffer attribute and to create a flow32 buffer attribute we want to reference a new 3 buffer attribute and this buffer attribute takes a float 32 array so to create a float32 array this is basically just a typed array with javascript typically you can just type an array in like this this is an untyped array types are assumed you can put different types in if you want such as a string or a number but with a float32 array we actually need to create a new float 32 array object so basically inside of this we're going to put an untyped array and we put an untyped array in here well it's going to make sure that all the numbers within this array are of the type float 32 and that is just something that's required in order to get this buffer attribute working now if i save this there is another argument that we need to add to our buffer attribute instantiation so right after float32 array at the very first ending parentheses we need to add a comma and then what is this last argument well it's going to be a grouping number how many numbers within this array consist of a group and we look inside of our array we know that every three indices here represent one position an x a y and a z basically this right here this number is the item size it says how many of these data pieces right here consist of one grouping to represent one value position has an x y and z three data types so if we were to do position right here would be three but if we think of what a color attribute consists of it's an r g and a b if you set those three values then you're going to be able to set the color of whatever it is you want to affect so since rgb is equal to three every three data pieces we have within our array is going to be one representation of one vertice color so we can just add three here within our new buffer attribute creation and we should be set to start altering our vertices colors so into our float32 array we're passing in three values this first one is going to represent r the redness of our actual vertex and the values for this are anywhere from zero to one it's not actually zero to 255 like you might be used to for rgb values so instead of using a three we need to make sure that we specify any value zero to one let's go ahead and make a specific vertex a different color let's go ahead and make it blue if we want to make one specific vertex blue we're going to give it a value of zero for red we're going to give it a value of zero for green and then we're also going to give it a value of one specifically for that blue data value so if we save this you might be expecting since we're only altering one vertice right here because we only have one grouping of three rgb that the very first vertice up here should have some sort of blue color associated with it which it doesn't the reason being even though we have this color attribute which our plane will read we need to make sure that we go back to our plane material right here and declare that we want to use vertex colors we're going to set this equal to true and you'll see once we set that to true while our plane just disappears completely and we end up getting an error in the console this is occurring because right now we're only supplying the color for one vertex in order to actually get this working we need to supply colors for every single vertex within our plane so in order to ensure we are supplying a color for each vertices within our plane we first need to know how many vertices does our plane have in the first place well we can find this by looking within our plane mesh geometry attributes if we look inside we now have an attribute for color which is great you'll see we're only supplying just three pieces of data to our color attribute when in reality if we look within any of these other attributes there should be 336 pieces of data and when we group each piece of data within this array and 2 3 well they're going to be 121 groupings of 3. we need to do the same thing for our color attribute we need to make sure that this array right here is equal to 363 and that its count is equal to 121 our item size is already three meaning that this grouping right here represents one value of rgb we need to make sure that we extend this array so how do we do that well the first thing i'm going to do is i'm going to create a constant called colors and this is going to be equal to an empty array the second thing i'm going to do is i'm going to create a simple for loop and we're going to be looping through our plane mesh geometry we're going to select our attributes which is everything we see right here and then we want to dive into our position attribute we can say we want to loop about 121 times that's how many groupings of data we need in order for this to work successfully so if we go ahead and console.log out i within this for loop it should go up to 121 which it does because remember zero counts as one so that is working correctly but now we need to push some colors into this array for each vertices so if we select our colors array and then push in an r a g and a b watch what happens this is going to be affecting every single vertices because we're running it for every single vertice based off of our position attribute to count so if i save this we're not going to see anything but if we go ahead and cause log out our colors array should be filled up with 363 pieces of data all of them are going to be blue because we set the r to zero we set the g to zero but the b value blue is going to be equal to one so how do we actually use this and set it equal to our plane colors attribute well right now we're only passing through the simple three value array we're going to go ahead and get rid of that and we're going to push in our colors array which we just populated with everything we need we save and everything turns black now right now since we just added in vertex colors a color for every single vertice within our plane what's happening is that color is interfering with the initial color we put within our mesh following material so when we're adding in vertex colors what we can do is we can take out the initial color we assigned and now our material is going to reflect the color we assigned with the vertices color instead so now everything is blue if i go ahead and change our vertices to something else such as green by changing the values right here where we're pushing into our colors array save you're going to see everything is green and then everything is going to be red initially if we set it equal to one zero zero so now that each individual vertices has a color associated with it what we can do is when we hover over a piece of the mesh that is close to one of those vertices we can change that one individual vertices color to be something else and that's what's going to give us that trail effect as we move our mouse so where are we actually tracking whether or not our mouse is hovering over the plane it's going to be right here where intersects length is equal to zero so this is where we intersect but this is also where we're going to be changing the color of each individual vertices so here if we look inside our intersects array this is an array because you might be able to intersect multiple objects we're going to want to select the very first item in the array and of course we're going to have at least one item because we're testing that we have one item right here and i hover over this and open this up you're going to notice that this has a face property inside of it this is the exact face that we're hovering over if i zoom out a bit and hover over this very first face in the top left hand corner and make sure i am opening up that object right here you're going to see that face consists of three properties a b and c and a b and c are representative of a grouping of data so for instance let's go ahead and say our color attributes are equal to something like this and of course we're going to have more data at the end of this let's go ahead and look at this well if we hover over this top left-hand corner and it gives us an index of zero a grouping index is zero well it's going to be referring to these three values right here this first grouping if we look at c that is going to be referring to basically the second grouping because we're using indexes which we always start at zero so if we go to the second grouping it's going to be these numbers right here and if we go to 11 well then we'd be referencing the 11th value within this iteration which would be further down the line something over here so when you hover over a face it's returning to you which group of data points make up the face that you're hovering over one vertices here one vertices there and one vertices there create a face this is the index associated with each of the groupings within your attributes array so what we're going to want to do is we want to select this face attribute that we get whenever we hover over something and we're going to be using the a b and c here and one of the other things we want to select let's go ahead and comment this out for now one of the other things we want to select is going to be what we're hovering over which is going to be the plane we want to select the object and specifically its geometry if we go ahead and save this hover over it looks like i just spelled intersex wrong i'm going to make sure we spell that correctly we hover over it well now we're getting our plane geometry and since we're accessing our plane geometry we can get all the vertex attributes associated with it we're going to go into our attributes object and then we want to make sure we select our color attribute hover over this and now we have our buffer attribute object which contains all the color data related to each individual vertices so let's say we stick with hovering over this top left hand face over here if we're to hover over that we want to make sure that we're changing these three values within our color attribute array so how do we do that well we're going to want to select our color attribute which we have right here and it has a nice little function that we can add on to the end of this such as set x and the first argument here is what index grouping do we want to select we want to select this first index grouping right here which is going to be zero and then to what the value do we want to set the x color of so the when we refer to x it's going to be the very first value within this grouping you can think of x as being r what do we want to set the r attribute two well we can go ahead and set it to zero whenever we hover over it and when we hover over our plane zoom out we're not seeing any color change in the top left hand corner just yet and that is because when you select your geometry attribute color you need to make sure that it knows to update the color based off of the action that just happened it needs to know that the data within its array changed so what you can do is you can select that color attribute give it a property of needs update and set it equal to true and once you do that and then hover over your plane scroll out you're going to see that one vertex now has a color of black rather than red we just set the r value which right here is x it's just a shorthand method we just set the r value to zero instead of one so if we look within our color attributes array at the very top open this up you'll see that we are giving the first vertices up here a value of red to start and then when we set its x it's r so these first three groupings we set to this one value equal to zero because we're selecting the first grouping index which is these three guys right here and we want to say set x the first value equals zero we change this one to zero that is what makes it black in the top left-hand corner so instead of selecting just the very first vertice and altering that we want to make sure that we are selecting all the vertices related to this face and altering all three of those instead and thankfully we can already get all the vertices related to the face we're hovering over by using intersect zero phase if i console log that out remember when we hover over this we get each index related to the face we're hovering over so using this we can go ahead and copy intersect zero face instead of setting our index at zero we know the exact index we want to set by using this right here so now if i save refresh and start hovering over we're not seeing anything just yet and if we put only face here we're only getting the whole object of phase which is a b and c all the indexes related to it but we want just one vertices at a time so we want to make sure we select the very first vertices of the phase we're hovering over which is going to be a that's going to give us the grouping we need and now we start hovering over this you're going to see that the very first vertice of whatever face we're hovering over is going to be turning black because we're setting its red attribute to zero which is indeed what we want to create this effect but right now it's a little janky because we're only setting the color of one vertice related to our face you'll see right here where my mouse is we only set this one vertex right here to be black but the top right and the bottom vertices don't have their vertex colors changed we want to make sure we're changing all the vertices colors for the face we're hovering over so we only did one which is the a value of face we want to make sure we're doing the same for the b and the c values of our face as well so all we need to do here is we copy this line of code and we want to make sure that we change face dot a to face dot b to make sure we're changing color for that vertices as well that we're hovering over so now we have two vertices changing their vertex color at the bottom left the bottom right we just have one more to go which is going to be the top one we need to make sure that we're also referencing our face dot c and those are all the vertices related to that one face we're hovering over so we save and now all the vertices of this one polygon right here this one phase should light up as black and darken as black so we hover and now all three vertices are indeed black and it creates for a much smoother effect with everything lighting up as you would like it too so looking at this over here this code is pretty sloppy just because we're duplicating our code many times this is a very long statement it's hard to read so something you can do to make this a little cleaner is object destructuring which we went over a little bit i believe in this video already what i'm going to do is we know we need to select the color attribute related to our object geometry which we're selecting using this long statement right here so what we can do is we can just go ahead and cut this out of where it is and assign a const of color we're just going to reference the color associated with this attributes object if we do things like this well now we can easily read our code to say we want to set our colors x value our r value equal to whatever code we have right here within its argument we can go ahead and do the same thing by getting rid of all this extra code right here because we're already referencing the geometry attribute's color we do things like this things are going to function exactly the same but obviously this is a lot cleaner as before because now we just have a small color constant instead of that long bc statement with intersex object geometry and attributes so right now we're only setting our red value equal to zero which in return gives us a black hover effect what if we want to change that to a different color well we need to make sure we're not just setting the x value the r value for our face vertex we also want to make sure we're setting the g value which is going to be y if we use the function set y we're going to be setting the middle piece of data within our array let's say our array consists of this right now to start rgb if we use set y we're going to be setting this middle value right here so if we set this equal to one our green value is equal to one and we set red to zero which we're already doing right here well now our hover effect should be green for the vertex we're hovering over so let's go ahead and do that we're going to set that middle value for our face a equal to one let's watch what happens we start hovering over things and at least one of the vertices is turning green the others are still turning black because we haven't taken into account the other vertices it makes a little easier we can comment out vertices one we're to see two for this code and then this last set x is going to be equal to vertices three so if we want to make sure we're not just changing vertices two equal to black we need to make sure that we're also setting its y value its g value on face b equal to one so now we only have one black vertices being set let's go ahead and change that as well we want to set that vertices on face c so that its green value is equal to one and now everything is going to highlight green as we begin hovering over this and you can go ahead and do the same thing for blue by setting the face a vertices z the third data value within the array equal to a value of one and this is going to change it blue you want to make sure you do this for every vertice within the phase you're hovering over so we said z here for phase b equal to one we change the green back to zero we do the same exact thing for our last vertices change the equal to zero we should get blue when we hover over this and it looks like we do and i just messed up a little bit here right now we're setting green equal to one for that one vertices we're going to change that to zero make sure that blue is one instead and now we get the hover effect we're looking for so this is exactly what you want to get some sort of highlighted hover effect is to add in your color attribute make sure it's populated correctly that your material has vertex colors turned on and that you set the vertex color equal to a new one within your raycaster intersects conditional i know it's a lot guys and i'm sorry if that's a little confusing it's a lot to take in at once but this is currently the easiest way that i'm aware of to get the effect you want to get it's probably a little harder than canvas but hopefully i explained that in a way that makes a little more sense than it would have trying to learn that on your own so if we look back at our to-do list while we successfully added in a hover effect and we are changing the surrounding vertex colors based off the intersected face we're hovering over so you might think well can't we just go on html now well not quite there are still a few things that we want to do to make this look a little better and start matching up with what we have over here the first obvious one is we want to change the color of this to match something over here this looks like kind of like a river or ocean of some sort which i really like so i want to make sure that we're changing our color to match up exactly so how do we change our color to match up with something along the lines of an ocean well where are we changing the color by default for our plane within our material is created right here mesh following material we took out the color attribute because it was interfering with our vertex colors attribute so right now the color of our plane is determined by our vertex colors which if we scroll down our vertex colors are determined right here by default they're going to be the r g and the b value we're pushing through into our colors array and then setting as our color attribute for our geometry so here we can give rgb values to be the exact color we want our plane to start out as and to save you some time to get the exact color we're looking for over here those values are going to be 0 for r point 19 for g and point 4 for our blue that's going to give us this nice ocean like blue color hover over it well we're still getting a neon-ish blue hovered over it because we haven't changed the color of our hover effect so we scroll on down where we're changing each vertex color within our animation loop these three values rgb are going to be represented of the color we want to add in whenever we hover over our plane and save you guys time here to match up the color of this light blue we want to make sure that we supply an r value of 0.1 a g value of 0.5 and then a b value of one and we wanna make sure we're doing this for each vertex of the phase we're hovering over so it's going to be point one point five and one and then point one point five and one as well we save this we go back to our app and now when we hover over this you'll see it has that same light blue color that we have over here the only difference is when we hover over things eventually the color changes back to normal to do this what's happening is each face we're hovering over we're setting the color equal to the new color we set within version one two and three but as that is being set we're also calling an animation function to fade the vertices back to their initial color and we can do this using a animation library called gsap if you haven't heard of it so gsab is to go to for creating animations without much headache to install gsap we're going to be using the terminal method the same way we installed vitae and dat.gui so what we're going to want to do is open up our terminal make sure that you're inside of your directory for your project and then we're going to run npm install g sap make sure that you save this so that it is installed as a dependency once it installs you'll see that it should be listed out within your dependencies within package.json and now you can import it into your main.js file so if you want to import a library it's typical to go to the very top and write import for here gsap we're going to be importing a gsap object from the gsap library and remember we can always test that it was imported correctly by console logging it out go back to our app look within our console scroll to the top you'll see right here this is actually the gsap library that we can begin using so now that it was imported correctly we can go back to our intersect code which is going to be down here so we're going to be changing all the faces vertices equal to a light blue but after that change happens immediately after that change happens we want to animate it back to its original color so using gsap we can call a 2 function this is going to be what do we want to animate to what do we want to animate in the first place the first argument here is going to be an object we need to create an object that consists of the rgb values of our initial color so what was the r value of our initial color if we forget we can always scroll back to where we are setting our rgb values for each vertex which is going to be right here so r is going to be zero g is going to be point 19 and b is going to be 0.4 so let's go ahead and remember that r is zero g was point 19 and b was 0.4 so we have an object for our initial color we're also going to want an object for our hover color this is what we want to change our value to so if we look at our r our r is simply point one our g is simply point five and then our b is simply one and we wanna make sure we're not calling this initial color but hover color instead so we know when we hover over this we're changing the vertices equal to this color so the vertices currently equal to what hover color is right here we want to animate these values down to our initial color instead so we can do is we can select our hover color object and then for our second argument we're going to be adding in two curly brackets to represent an object full of values well what properties does hovercolor have well it has an r it has a g and it has a b these are the values we want to animate but to what value do we want them to animate to well we have those values right here within our initial color object so we want to make sure we're bringing point one down to zero so what we can say is we want our hover color r to go down to our initial color r we don't want it to stay at point one we want to do the same thing for our g and b values so hover color g is going to go down from point five to point nineteen and then hover color b is going to go down from one to point four so this is going to interpolate these numbers right here down to here and we can see this in action by adding in an on update property that is assigned to an arrow function within our second argument object right here if we can't log out update to start and we can hover over this you're going to see update is called multiple times because this is running an animation i'm going to log out the values of our hover color hover over this and you'll see that those values are slowly shrinking towards 0.19 and 4 over time even if we begin to hover off of this this is still going to run it doesn't matter if we're no longer intersecting the plane but why isn't the color actually updating whenever we hover off of it well although we are changing these values right here to go back to the initial color we're not actually setting the values within our geometry we need to make sure we're doing that so all we really need to do here we are going to select where we are setting our three vertices which is right here and we're going to be pasting that in to our on update function and now since we are setting our vertices colors within here we can reference the value that is being interpolated which is going to be initial color r initial color g initial color b and we want to do the exact same thing for these three guys right here and if we save this and start hovering over you're going to notice and not really working and that's just because another mistake on mine happens from time to time for sure is remember we're not animating the initial color we're actually animating the hover color so if we want to get that smooth interpolation we need to make sure we're setting the vertices colors equal to our hover color for each frame this animation runs so now if we save with the hover color and begin hovering over this you're going to see it has that nice fade out effect over time and eventually goes back to our initial color which we declared right here so really cool thing to get that water trail effect so looking good one of the last things we want to do in order to get a good home page is we want to make sure we tailor this to the exact dimensions we want when a user lands on it so if i were to change my width or my height you're going to notice that our background turns black and it doesn't have any hover effect associated with it we also get a bug in the console now why is this happening well let's go ahead and inspect where we are setting the color for each individual vertices well let's get rid of some console logs clean up our code a little bit you're going to notice that we are setting the color for each individual vertices right here but whenever we affect our width or our height well we're calling that within our generate plane function as you can see right here with gui add so we need to make sure we're also calling this code right here whenever we are generating a new plane to ensure that it has the new vertex colors so one simple thing we can do is we can just copy this code right here scroll on up to where we are generating a plane get rid of any excess code we don't need and after we are setting the new positioning of our vertices we can go ahead and set the color of them as well so now when we affect our width we maintain that color when we affect our height we maintain that color and we still have the hover effect and the cool thing is this works no matter how many segments we have or what width or height we have as well we still have the same exact power effect occurring so how would i tailor this piece right here to look something more like this on a refresh well the very first thing i would do for sure is i would enlarge this to the correct width or height so if we go ahead and enlarge this well that goes ahead and it reaches the edge of the screen but now we don't have as much dimension here because we don't have as many segments so if we begin turning our segments up we're both width and heights let's go ahead and just find something we like i personally like a little more segments than a little less i think that looks good we'll go ahead and call this 1919-1717 for something that i personally like you can set this to whatever you guys would like on your own so if i want to change the default in which this plane is spawned at well where am i creating my plane geometry it's going to be right here new 3-plane geometry and we have all these hard-coded values so really for our width i'd want to put in 19. for our height i'd want to put in 19 as well matching them up with what we have in the top right hand corner here and then i'd also want to change my width segments to 17 and my height segments to 17 2. so if i save this you're going to see that the plane spawns with these new attributes which is perfect but one issue is is now the defaults for our dat.gui object up here aren't the same they are not matching up with what they actually are so to fix this what we can do is we can go back up to where we are setting our plane object and we're going to change our default width to 19 our default height to 19 i believe with segments with 17 and same for height segments and if you don't want to have to keep changing these in two places you can go back down to where you are setting the attributes for plane geometry and you can just reference the gui object directly so it was world plane and then width so this should maintain the width assigned through that dot gui you'll see we have it with the 19 still that is perfect we can do the exact same thing for our height and then the exact same thing for our width segments and then our height segments as well so on save now we are referencing all the data from that data object up top and if we want to change the default value for both our plane and the values for the sliders right here all we have to do is change the value within this plane object you'll see the default changes and the plane actually changes as well so that's perfect that's exactly what we want we'll go ahead and maintain what we came up with which is going to be 1919 1717 so now if i go ahead and exit out of this it's always good to test what this looks like in full screen as well see if that's something you like i think that's pretty good honestly i might expand this just a little bit more so what i can do is if i want to expand my width and height i can change the max value for our width to be something a little larger something like 50 for both width and height and now i can expand my width and height and play with this a little more let's go ahead and make it something like 24 and i want more segments 24 and 25 25 is probably something i'm pretty happy with and now you can see since we have the orbit controls in place if i click and drag well we have this nice plane laid out and you can always expand this more by playing with your width and your height attributes over here to make it a little larger based on whatever you'd like and the very cool thing is with raycaster and the vertex effect well the hover works no matter which angle we move our object at so really really cool stuff right here to play around and create this geometric background so we tailored this to the exact dimensions we want but one thing i actually forgot to add in here i'm going to add this in now is add vertices movement so if we look at the original and we scroll in you'll notice that these vertices are actually moving in randomized directions but they're not actually going off the screen or affecting the plane in some way to where it just doesn't look good they're just moving in a controlled motion around each other and it creates for this really cool kind of wave like effect here we don't have that you should you could technically get away with this if this is what you want but if you want to add that movement effect well we're going to need to do a little bit of editing specifically within our animation loop if you want something to move in a controlled motion back and forth between a specific point one you're going to need to use sine or cosine functions those are two functions that are always going to return a value negative one to one and since they always pulse between negative one to one we can affect a certain position to pulse between two specific points and two we need to be able to track the original position of the vertex we always want to reference that when using math cosine and sine functions because the actual position of the vertex is going to be changing we need to make sure we're referencing the original position of the vertex to get some sort of pulsing effect so that's going to be the very first thing we do is we're going to store the original positioning of each individual vertices within a new array so if we scroll on down to where we are setting our vertices positions i'm just going to add that in here vertices position randomization i'm going to add a quick label right here color attribute edition just so i know what this code does makes it a little easier to read here we are only setting the z positioning for each individual vertices if we'd like to randomize this a little more we can change this so that we're also setting the x and y to be a little more randomized so let's say we want the x position of this vertices to be somewhere over here or over here just randomize things a little bit well first we would have to select the x position which is always going to be the first iteration of what we're looping through you'll see right here array i is equal to x so we're going to be setting x equal to the current x value plus math random now math.random returns any value 0 to 1 any randomized value but if we add that zero to one onto this point right here well that's only going to push it in the right direction we need to make sure that we're able to get a randomized negative value from this as well so if you subtract 0.5 from math.random well let's think if we subtract 0.5 from 0 well we have a value of negative 0.5 but if we get the high end of math.random which is going to be 1 we subtract 0.5 we're going to be getting a value of 0.5 so this is a good way to get a random value anywhere from negative 0.5 to 0.5 but it might not affect the vertices as much as we wanted to if you want to affect this a little more you can always multiply it by a larger number such as 2 or 3 and that's really going to alter the exposition of your coordinate i think 0.5 was fine honestly so we're just going to go ahead and stay with that and let's go ahead and also alter the y positioning as well to select the y positioning what do we need to do we need to select i plus 1 that is the y coordinate make sure we are using the current y coordinate and then adding on a math.random value minus 0.5 so we get a negative value as well possibly and that actually looks a lot cooler than we had it before but remember to add in that animation we need to store the original position and then alter this position right here these positions are what we need to alter within our animation loop but we always need to reference some original position so to create an original position what we can do is we can select our plane mesh get our geometry go to our attributes since we want our position attributes and it's always good to console log this stuff out to see what exactly are we dealing with so if i were to console.logs out and look in our console you'll see that this is console logging out a float32 buffer attribute inside of here we have quite a few properties including the array that we're going to be editing to affect the actual movement of this vertices but what we can do is we can add an additional property in here that is just a duplicate of the array that is never going to change but we're going to be referencing that duplicate to create that movement effect that goes back and forth so what i'm going to do is i'm going to select our attribute stop position and i'm going to create a new property called original position and all this is going to be is equal to our position attribute and specifically the array inside of it so now when we log this out after setting this we can open up this object again and now we have a new property original position it is the exact same thing as our array which contains all the data properties for editing each individual vertices so to start animating these we want to go to our animate loop which is going to be right here and we want to make sure that we're looping through this array which is our positions attribute array so we're going to do this above our raycaster this doesn't require any intersection or anything like that we're going to create a for loop and what is our array length well what do we need to access we need to access our plane mesh it's geometry its attributes specifically its position attribute and then we want to access its array this is how many times we're going to loop through this and remember whenever we have an array we need to specify its length to get an actual number so we're going to be looping through this about 2028 times and if you want to clean up your for loop remember you can always take that long object property and use object destructuring to grab the array and set it to a new constant so here we can just reference the array directly with a small version of it and get its length so right now we're looping through that giant array about 2028 times for every frame to make this a little more performant we can just select each data value as groups of three because we know each position has an x a y and a z so same thing like we did earlier for one of the groups instead of adding one onto this for loop we're going to be adding on three so now we're looking through substantially less times and here we want to set our position for x y and z to be something different over time so what we're going to do is we're going to be setting our array i this is always going to be the x coordinate and to get some sort of pulse effect this is going to be equal to the original value and remember the original value is within this position object so not only can we reference our array through object destructure and we can also reference our original position we're just pulling it out of this position object so we can do is we can set our array equal to the original position i so basically the x-coordinate of this is exactly the same as the x-coordinate of this but to create a pulse effect we always need to alter the original value without actually altering the value that actually moves the freaking thing on the screen so if i save this and refresh nothing's going to happen nothing's going to move but if i add on to this original value over time a math dot cosine function which takes an argument of radians to say fancy version of degrees if i begin to increase the value within this argument this math cosine function is always going to return a value negative one to one and it's just going to pulse between negative one to one over time and if we're continuously adding on negative one to one to our original position we're going to get a movement effect on the x-axis for whatever vertices we're looping over so if we want to change the value of this over time we're going to go outside of our animate loop and create a let called frame this is going to be equal to 0 to start and then for every frame we actually loop through we're going to be adding a small number on the frame over time this is going to represent what frame we're on how many times we call this animate function and now that this is increasing for each time we loop through animate we can put it within our math cosine function so we're going to put frame here so if we add frame on in there we're not going to see anything just yet we can always test if this is working by only looking for the first iteration of this loop so we don't bug out the console what we can say is if i is equal to 0 meaning it's the first iteration of this loop let's go ahead and console log out math cosine frame to make sure that this is actually increasing and decreasing as we want to you'll see it's going down down down until we hit negative one perfect and then eventually it's going to go back up until we hit one so we know that's working and we know that array should be affected we can also console log this out to make sure that's working as well array i and indeed that value is changing for the vertices we're looping over so why isn't it actually being affected right here well the reason is when we are updating our position right here and we're animating it we need to make sure that we're telling our attribute that it needs an update so if we set this equal to true we save you're going to see that it just immediately moves off the screen and eventually it's going to come back so we do have the pulse effect for each individual vertices but they're all moving at the exact same time so that they go way off the screen and eventually they pulls back to the left side of the screen so if this is happening what you can do is you can set math cosine to be something a lot smaller to make it a lot smaller you can multiply it by a value 0 to 1. we're going to multiply it by something like .01 you're going to notice that the x value is moving left and right but this isn't really the effect we want we want each individual vertices to be moving in a random position independent from one another so rather than each vertices have the same value produced by math cosine frame we need to add some random value inside of this for each individual vertices so where we are looping through our position right here we can we can do all the work to add in a random position for each vertice as well right now we are looping through every three iterations and each three iterations are going to have their own random value but to access these random values in kind of like a buffer format where everything's stored in an array well we're going to want to create an array called random values this is going to be equal to an empty array to start and as we're looping through each vertice in this random values array we're going to push in a new math.random value so at the end of this after we go through the whole for loop for console.log out random values we should see a list of random values and to clean this up let's go ahead and get rid of any additional console logs make sure we're only looking at exactly what we need i'm just going to command f to make sure we're only logging out those random values it looks like i got everything deleted them and these are all the random values we have an array of 676 which should be how many vertices there are within this default plane so now that we have this random values array let's go ahead and attach it to our plane mesh position attribute similar like we did right here with the original positioning i'm going to reference random values onto this set it equal to our random values array so now when i console log out our positions attribute console log plain mesh geometry attributes position we should see those random values being stored in here and there they are you'll see we have a vertices count of 676 we also have 676 randomized values that we can now use to make sure that these are moving at different rates compared to before so now that we have these random positions we can begin to insert them within our math.cosine function here so what i'm going to do is onto frame i'm going to add on our random values array and if we just want to reference random values exactly like this we need to make sure we're pulling it in from our position attribute so here where we are destructuring stuff i'm going to make sure that i'm pulling in random values and we can't add on an array to a frame we need to make sure we are accessing the random value within the array we are looping through so to get that simple enough all we need to do is reference i if we constantly log this out and look inside of our buffer attribute you're going to see now we have this array full of random values but there is one issue here the array we're looping through to change all the positions is this array which consists of 2028 values we need to make sure that this random values array is equal to that or else we're not going to have a randomized position for both x y and z we're only going to have them for x so what we can do is within our for loop where we are populating this random values array is we know we need three times as many random values the reason we're not getting three times as many random values right now is because we're skipping over every three values within this loop so what i'm going to do is i'm going to change i plus back to i plus plus which means we're adding 1 onto i we're looping through every value within array.length rather than every three values but we know this code right here is dependent on looping through every three values so if i want to make sure even though this for loop is looping through every value if i only want to activate this code for every three values i can use a modulus operator so i'm going to say if i divided by three has a remainder equal to zero then i want to run this code this is going to give us the same effect for everything we have right here but at the same time we're going to be able to push in a random value for every iteration of this loop so basically we only have to call this for loop once but we still get the best of both worlds because we can call this code and we can also call this code so go ahead and save this and then look within our array again and now random values does indeed have 2028 values and our array positioning is still altered correctly because we're only calling this code for every three items within our position array so that's looking good but let's go ahead and start animating these correctly with our randomized value so if i go ahead and scroll on down we want to make sure that each vertices has a different value outputted by math.cosine so we have frame which means everything is going to be the same but we want to add on that random value so we need to access our random values array and if we want to access this directly we need to make sure we are destructuring from our position attributes object so we'll make sure we add it in right here and you can't add an array onto a frame we need to make sure we are selecting the exact value we want to add onto this so i'm going to put i right here which is going to select the value we are iterating through we'll put i there and now you'll see the x values are much more randomized everything's not just pulsing back and forth but they have their own little direction in place so this looks like a lot of movement i'm going to slow this down even further by multiplying this by a lower number and even that might be a little too low so i'll increase that a little bit and just go to taste to something you like think for how big our plane is i think .003 is going to do but let's go ahead and make sure that this is also randomized in the y direction so simple thing i can do is i can just copy this line of code that we just created above it i'm going to comment y this is the y coordinate that we're going to be altering and to select the y coordinate within our buffer array i'm going to add 1 onto i that is going to be where the y coordinate is i'm going to do the same thing for the original position because we want to make sure we're grabbing that initial value and setting the new value equal to that and then we're going to be calling math.sine instead of math.cosine cosine and sine work together to create full circular motion so if we add sine onto this instead of cosine we're going to get a much more randomized effect compared to if we're just using cosine for both so if we change cosine to sine here and then make sure we are referencing not just i but the second value within our randomized array we're going to get something that looks even more randomized and you'll see now the y coordinate is randomized as well but there's still one little thing here and it kind of looks like all of our vertices are moving in a circular motion in the same direction if we want to randomize this even further remember the trick i told you about getting a negative value with math.random as well well when we're pushing in values into our random values array what we can do is subtract 0.5 from math.random to make sure that things are going to be in a different direction so i save this so now you'll see we have a lot more randomized movement in the y direction so this is definitely something you can keep if you want to get closer to the original like we have over here you're going to want to copy these attributes and i know i said i wouldn't come back to these but just for the sake of completing this as close to what we have over here let's go ahead and change these values to match up with what we have in the original piece so we know our width right now is 24. we can change those at the top where we have our data object for gui we're going to change our width equal to 400 which is what it was in the example piece same for height that is also going to be 400 go back to the example reference what we have width segments is going to be 50 height segments is going to be 50. change 25 right here to 50 let's see what we get well now we are just way too zoomed in an easy way to fix this is to find your camera z position and set it to whatever you would like to make sure that it's further away from your plane i'm going to set it equal to 50. that's definitely going to pull it away a lot further but now we don't have as much depth as we did before with this larger plane so we want to go to where we are randomizing our vertices position and you can see right here this is where z is randomized well right now they're only being randomized where the z vertices come closer to us remember if we subtract 0.5 from math.random well now they can go further out or closer to us because we're getting any value negative 0.5 to 0.5 but there's still not a lot of depth so if you want more depth in either direction we can just multiply this by a larger number and now we do indeed have a lot more depth so we're looking pretty similar to the example piece over here but you'll notice the example piece is a little darker if we want to make this a little darker well it's going to be based on our light positioning over here the light positioning is closer to us and above the plane but if we look over here and we look at our light positioning while we're just sending it further to us and looking directly at the plane but there's not really any angle in the y or x axis if we want to make sure that it's shooting at an angle we're going to get more shadows which gives it more depth so what we can do is we can set its y position equal to one which means we're going to be moving it upwards at a 45 degree angle rather than just facing the plane directly if we save that well now we have that depth we're looking for it looks very similar to what we have over here maybe it's just in a different direction that takes care of the color but there's still something just a little off if we want to tailor this even further let's go back to where we are randomizing our vertices position and our x and our y's are kind of lining up with each other right now if i go across this you'll see all of our vertices are almost creating a straight line almost and over here they are just much more differentiated from each other so if we want to differentiate the x and the y a little more to create less of a more straight edge effect what we can do is we can alter the set y position to be a little larger than it was before so we're going to multiply our y by three we're also going to multiply the x for our vertices by three as well randomize it a little bit more and now that is pretty one to one what we have over here maybe just a different direction but you still get the same exact effect that we have in the example piece play around with these a little bit to really get different effects and you can see just how much it really changes the landscape you're working with i'm going to stick with these variables and then i'm just going to make sure that our dat.gui is fixed so instead of limiting with the 50 i'm going to make sure that this can go all the way up to 500 and then i'm going to make sure our segments can go up to 100 and now we have the ability to alter this but we're almost done with this plane thing completely if i go ahead and alter this just a little bit you're going to notice that our polygons are a little messed up and we also get an error in the browser this is due to the fact that things such as our random values and things such as our original position are only being created on load we need to make sure that these are also being created whenever we change when the sliders up here so what i'm going to do is where we are randomizing our position i'm going to go ahead and take all this code go up to our generate plane function i'm going to paste it in we have duplicate code right here which is our old randomization code we can go ahead and get rid of that we save we're not going to get anything right here because we're not calling this randomization code things that stores properties onto our position attribute array like we need it to so what we need to do is we need to make sure that we call this generate plane function after we actually create our mesh and you look inside of this function we have all of our color setting done right here let's go a little further down we have the exact same code right here we can just go ahead and get rid of that because we're going to be calling it again using the generate plane function so after we create our mesh we're going to generate a plane which has all the randomization in it and we still get the same effect but now once we go ahead and change the value of height and width things are randomized as before our hover effect still works and our colors are still taking place you can change pretty much any value here to get the exact effect we want without anything breaking in the process and one more thing that touches up i promise this is the last thing if you notice you're getting too much of a circular movement here what you can do is where you are populating your random values for this array we're just going to look for random values this seems to be where we are populating things we're only pushing through any number 0 to 1 within this random values array but math sine and cosine if we want to extend the full random range of negative one two one we need to make sure that we're supplying cosine or sine with a value of six point two eight pi times two so really instead of just any value zero to one we want to make sure that we're supplying math random times math pi times 2 which is going to give us 6.28 we're going to be getting any number 0 to 6.28 instead within this random value array just make sure that you multiply that value right there or else things will break and now that is going to be a lot more randomized compared to what we have before you can even test this if we can't really see your movement too much you can either zoom in or you can go back to your animation loop increase this factor right here by something larger such as point one and you should be able to see your animation a bit better do the same thing for y and now we're going to have true randomization for each vertices compared to what we would have had beforehand where everything is just limited from zero to one okay so finally looking at our to do's we added in vertices movement all we have to do now is add in html and integrate with javascript this is the easiest part in my opinion apologies if this is a little hard to grasp guys it's a little hard for me to teach to be honest so to add in html let's reference our beginning piece we're going to go ahead and see that we have our name we have this little headline and then we have a button which is going to go to some other page on your website so to add in html to this we're going to go on over to index.html and here we're going to start adding our markup so you can do this within this default id app or you can do it without it it doesn't really matter we're going to go ahead and write our markup inside of this what is our markup look like right now well we have this one container that consists of looks like a headline another headline and a button so let's go ahead and make another container it's going to be a simple div and then we have this main headline for our name the first headline in my opinion should always be h1 even though it's smaller so i'm going to go ahead and make this an h1 tag and then pretty much anything under a headline i by default make a paragraph tag and then i need to make sure that i add a button to this as well so i'm going to add this button markup it's going to be called view work and remember this is the finished product we need to make sure we're going back to the one we're working on if we look at our html this is what it's going to look like by default we need to make sure that we alter it to look something like this and that we can still interact with our background in the process so to start styling this with css the first thing we want to do is get this one div if we inspect this div by clicking on this button in the console inspect the div we need to make sure we get this div laid on top of our canvas piece or 3js piece how do we do that well if we want to take it out of the document flow meaning we can overlay it on top of other things we can give it a style of absolute so what i'm going to do is within the style tags right here i'm going to add an additional style called simply.absolute and this is going to have a position of absolute so now if i add this class to our div right here it's going to take the style of position absolute i'm going to add that on and once we add on position absolute you'll see it's taken out of the document flow and it's overlaid on top of things next up let's change the color of the text so it's white and it contrasts a little better than what we see right now so to make sure our text is white i'm going to create a class called text white this is going to have a color of white so now i can pretty much just add this to our default div and all the stuff inside of it minus our button is going to have the text of white so text white save and now our text is white which is perfect so you'll notice the way i'm writing css i'm writing these using utility classes basically each class gets one style associated with it and the reason for this is it just makes your html super easy to write rather than thinking of a name for a class such as container wrapper or something along lines that you don't have to think of a name because all these names i'm coming up with represent exactly the style that is inside of them at the same time these are all standardized using a framework called tailwind css basically what i'm doing here is i'm replicating the style of tailwind css but eventually you're going to get to the point where writing all these classes is super cumbersome and tiring so rather than write all these manually what we can do is we can go ahead and visit tailwindcss.com search for get started click on read the docs and we're going to do a command f for cdn tailing css doesn't recommend you use a cdn just pulling in the framework using a link because there's a lot more customization available using their other installation method but for our purpose of just getting this inner project and using it this is totally viable so what i'm going to do is i'm going to paste this link right above our style tag and just like that we now import a tailwind css into our project and we can use all the styles associated with tail and css including things like absolute and text white we can get rid of these two classes right here save and now you'll see that our text is still taking on the styles of absolute and text white with a few things even different because tailwind css has a reset associated with it it says some default browser styles equal to their bare bones equivalent so adding 101 css is pretty good in my opinion for giving you a full css reset while allowing you to use all the nice classes within the library so i'm going to walk you through how to style this exactly with tail and css so we know looking at our example over here our text is centered so tail in css has a class of text center what does this do well it centers your text easy enough if you're ever unsure of what class you should be using with intel and css you can go on over to their docs search for anything such as a line text align and you're going to see the exact classes you can use so we just went ahead and used text center and now our text is centered but next up we want to make sure that this text the whole container is actually centered directly in the middle of our screen so we're going to do this using position absolute this is a little trick from the old days but it's still relevant today we want to make sure that within our div right here that we add a style of top this is going to push the container down from the top of our page down 50 percent of our browser width well the container width so it's down fifty percent but you'll notice it's not exactly centered if you want to exactly center this you can add a style of transform translate y negative 50 percent and now this is going to be centered vertically perfect in the center so we want to take these two styles that we just wrote in line within the browser and make sure that they're within our code so that they take effect permanently so i'm going to add in a style tag and i'm just going to add in two inline styles here there's nothing wrong with using an inline style don't let anyone tell you otherwise if you need to get some quick style code in there that's not until in css this is how you're going to want to add in a style you don't need to write a separate class or anything in my opinion it's just extra work so if we add in the style right here you'll see that now on refresh everything is centered vertically perfect but how do we center things horizontally well if we set our left attribute equal to 50 it's going to do the same thing it's going to push it over 50 from the left-hand side but we need to make sure that the center is within the center of our screen so what we can do is instead of translating y we just use translate which takes an x value for its first argument so x is going to be pushed to the left by negative 50 percent and then the y value for its second argument so we're going to push it back up by negative 50 percent and now this is centered perfectly in the middle of our screen and the cool thing is if we inspect our div it's only taking up the exact width of our content so our hover effects are still going to work as we move our mouse around our actual object there so starting to look pretty good but if we look over at the piece we have fonts that just look way better picking out the right font takes a little bit of experience in my opinion but let's go ahead and use the two fonts that we already have in place if i go ahead and inspect this piece we can see what fonzos are and you'll see that this is actually a font of x02 so this is a google font if we want to add a google font onto our page we're going to go ahead and search google fonts we're going to go to the google fonts website and then we're going to search for that font exactly so this is the font i was using and i was using the italic variant i'm pretty sure i was using regular so if we want to select this font i'm going to go ahead and select this style and you'll see that it gives you a link in which you can use to import it into your project so right above our tailwind link i'm going to paste in that google fonts link and it gives you a little bit of code on how to use this within your project if you'd like to use this within your project well you have to set your element to have a font family of xo2 sans serif so tailwind doesn't know we want to use this font as a result we're going to have to create our own font class and the name of this font is xo so i'm going to create a class called font xo and set it equal to font family x02 so going back to our app now if we assign our paragraph tag to have a font of exo now we are using the same exact font we got from google fonts because we are pulling it through google using a link tag and then we are setting this font xo class equal to x02 and then finally using it setting our paragraph class equal to that font so off to a good start looking back over here you'll see up here we have some sort of mono space font where each character is the same length as the next one it gives for a very techy feel because if you look at our text editor over here this is using a monospace font as well you don't want some sort of font that has different widths for your text editor because you want to make sure that you have some sort of standard in place for when you look at your code everything is in the same spot not based on some specific character width so this is a mono space font let's go ahead and use a new google font to get this in we're going to go back over to google fonts i'm going to exit out of this i'm going to scroll up to the top go back to the home page and i'm going to search for mono so a mono font that i really like actually is going to be the space mono font it's something i've used on another project and i like it a lot so i'm going to go ahead and select this this is just going to be a regular version of it so i'm going to select the style if you don't see the little pop out on the right like before you're going to want to scroll onto the top make sure you click this and now we have two font families selected x02 and space mono it's going to generate a new link for us that pulls in both of these at the same time so what we can do is back at our previous link we can delete these two that were supplied to us by google prior and paste in the new one so now we have access to two fonts rather than one and the nice thing about google fonts is it tells you how to use them so we're going to create a new font called space mono and this is going to be equal to font family space mono makes sense so now that we have this font pulled in we can set our h1 equal to font space mono go back to our app and now we have that mono font in place so now we just have to set these fonts to the correct height the correct font weights and so forth to really get these looking good so whenever you want some sort of sub headline such as your name and this should be the main focus you want to make sure that sub headline is de-emphasized a great way to de-emphasize text is to make it smaller we can give this a class of text sm that is going to be 14 pixels you'll see that smaller it's a little bit de-emphasized compared to this another way to de-emphasize text is to make the other text larger so if we want to make this text larger we're going to select our p tag right here and give it a size of text xl so that's a little bigger we can go ahead and make this even bigger by adding in a 2xl and i think i like where that is at so our text is de-emphasized at the top this is obviously our focus and you can keep this as is that's totally fine but something i like doing for my sub headlines is i like making them uppercase i just feel like it looks a little better so for my sub headline i'm going to give this a class of uppercase and whenever you have sub headline uppercase text it's always good to give it letter spacing make sure that each character has breathing room from the one prior or after it so what i'm going to do is add in a tracking wide class which is going to increase the letter spacing between these letters you'll see it increase very slightly and this is something i really like i'm definitely going to be keeping this so i do want to differentiate this text down here a little more from the sub headline so what i'm going to do is i'm going to go back to google fonts and for x02 right now we're using regular 400 italic i want to make sure that i'm using the bold version of this instead so i'm going to scroll down to the bold italic version which is this right here need to exit out of this select the style scroll up to the top you'll see that this is where the regular 400 italic is we can just go ahead and remove this because i don't want to use it anymore so now we're pulling in the bold version of this font how do we use the bold version of this font well we simply pull in this new google fonts link go back to our app and now we're pulling in that bold version so it's differentiating our text a little more from the text up here now something about this just looks a little sloppy and the reason it looks a little sloppy is because this text isn't anti-aliased anti-alias means that the browser is going to apply some effects to make sure that the edges of your text are as crystal clear as possible and you can see this in action if i go to my body tag and just start typing in anti alias we're going to get this style right here webkit font smoothing anti-aliased you're going to see we get this bold chunky a little dirty text but once i add it in things are a lot more clear than they were before so whenever you have any project you want to make sure that you're adding the style to your body to make sure that all your text is as crystal clear as possible so i'm going to go ahead and add that in there set this eagle to anti-aliased like so and now that's going to take effect by default so if we go ahead and compare our piece to the one over here we're looking pretty similar let's go into full screen it so we get the full view of things looking pretty similar the only difference right now is our text is a little smaller compared to what we have right here so that's something we can do is we can go ahead and increase the size of the text a little more this is going to be text 3xl go ahead and compare that maybe we want to go one size higher text 4xl so if we go and check our example piece go back and forth this looks pretty close it's not exact but at the same time our new one is looking just as good all we really need to do now is style our button to look something like this so let's go ahead and do that on top of our button we want to add a class we're going to add in a border to our button using tailwind you'll see it automatically adds in a white border how nice is that it's going to give it some padding if we select our x-axis padding and add in one round of padding by using px4 you'll see it's going to expand it by a little bit let's go ahead and do the same thing for the top typically within a button you want less padding on the top and bottom side than you would on the left and right side so our vertical axis padding is going to be a little less and that's looking pretty good as well let's round the edges of this button by using rounded large and then this button text just looks way too big for me so what i'm going to do is i'm going to shrink it down to text sm and to keep the font styles consistent i can change the text of this to match my sub headline up here so all i need to do to do that is select font space mono and add it on to our view work button and remember every time you have a mono space font if you're using it as some sort of label or button it's usually better to make it uppercase just looks a little better in my opinion and that is looking pretty techy looks very professional something i like the button is obviously too close to a headline up there so what i'm going to do is add a margin top a four that's going to push it we can push it up even further by adding on eight and that looks pretty good maybe i'll even go to 12 just give it a little more breathing room i think i did like it with eight a little more it's just kind of like a taste thing at that point and this looks really cool but right now we don't have a hover effect so the user may not know that this is actually a button so to add a hover effect i'm going to use a tailwind prefix called hover this is a really really nice way to add hover effects to stuff is you can just type in hover behind any class that you want to use within tailwind and whenever you hover over it that new class is going to take effect so let's see when we hover over this what class do we want our button to be well we want to give it a background of white so we just select the background white class from tailwind and now when we hover over this the background is white but now we can't see our text so we'll add in another hover class what color do we want our text to be on hover well let's say text gray 800 so now when we hover over it our text color changes and we can actually see it it's even cooler with our little background effect on the actual 3ds piece because it lights up the button in the background as we hover over it because it always follows us at all times so the very last thing i'm going to show you is how to link this button to another website to make this button link to another website we're actually going to change the button to an anchor tag by changing button to a we're going to give an href attribute which specifies where do we want to link to well if i want to link this to let's just say chriscourses.com i can just go ahead and grab this url plug it within my href code and now when i go back to my app you're going to see one the styling is messed up but now when i click on this it goes to chriscourses.com why is the styling messed up well the styling is messed up because by default anchor tags have a class of in line which means things like margin start messing up along the way our margin isn't taking effect because it has a class of inline by default so instead what we can do is we can assign a class of inline block and just by assigning an inline block it's going to make sure that the margin takes effect and that it is positioned correctly so now when i click view work it goes to my new website or whatever page you would like to use but we still have all the effects of being able to move this background we can even zoom in and out if we would like because we have the orbit controls still on it we just have this really nice background effect compared to what we would have otherwise would just having text on there it's great for something that really wows your visitor as they come and visit your website so i know this is a long tutorial but hopefully you guys learned a ton in the process if you would like to learn more about how to extend this even further such as adding in browser responsiveness so that your canvas expands the full width of the browser and in addition something else i'm going to be teaching is how to create this transition effect that turns a camera and bolts into an array of stars if you would like to learn how to turn this piece right here into that then be sure to head on over to the premium course in the description of this video i'm going to be supplying the first lesson for free otherwise i hope you guys learned a lot and i'll be sure to see you in the next video peace
Info
Channel: Chris Courses
Views: 45,333
Rating: 4.9321623 out of 5
Keywords:
Id: YK1Sw_hnm58
Channel Id: undefined
Length: 155min 25sec (9325 seconds)
Published: Tue Mar 30 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.