JavaScript project tutorial for beginners [HTML Canvas Particles]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] is it just me or do you think we need more creative coding tutorials on youtube there are a lot of videos teaching you the basics of programming but how is supposed to learn some of the more interesting effects that's why i created this series where we combine basic fundamental javascript techniques into creative coding experiments generative art animations for websites and more for science of course in today's javascript project tutorial for beginners i will show you something new we will create simple particle system on html canvas element and we will give particles some basic physics i will show you how to simulate wind and gravity forces then we will learn how to make particles bounce and we will set up collision detection with a regular website element for example h1 title element but it will work with any html element you choose even with multiple ones if you want to have particles that react to your website menu and articles for example at the end of this tutorial you will be able to create a background for your website with particles that respond to any html element of your choice i have already tried to do something similar once before but this time i have an improved very simple reusable solution i will also show you how to create different skins for this effect using for example liquid filter or constellations effect let's learn javascript together join me for another particle systems experiment [Music] hi coders welcome to my javascript laboratory where we use html css and javascript to create all different kinds of interactive animated effects that includes games generative art web design elements and much more in each tutorial i take you step by step through the code base as we build our project completely from scratch and that's not all we don't use any libraries or frameworks so not only we build cool stuff but in the process we also learn fundamental javascript techniques these techniques are completely transferable to other kinds of front-end web development projects and will help you to pass your coding interview and get your first programming job learning how to code is a big journey some of us take and my goal is to try and keep you motivated by showing you all different kinds of cool things you can build with javascript if you decide to commit and stick with it for a while i am here to help you to achieve your goals if you want to make me happy you can click the like button you can also leave a comment even just to say hi it doesn't have to be a long message or question would be nice to know who's watching let's build some generative arts today you ready then get some coffee and fire up your vs code let's go [Music] in index html i link style css and script js files and create html5 canvas element with an id of canvas 1. in style css i do basic style reset to make sure everything appears the same across all different browsers i use asterisk selector to target all elements on the page and set margin to 0 padding to 0 and box size into border box this means elements border and padding will be included in its total width and height i give canvas position absolute background blue just so we can see it for now top zero left zero with hundred percent height hundred percent next i will target id title one actually i haven't created this element so back in index html i create a h1 element with an id of title 1 and i give it text that says for example javascript back in style css i give title position absolute top 50 percent left fifty percent transform translate minus fifty percent minus fifty percent will center the text both vertically and horizontally in the middle of the page i change font size to 120 pixels line height 210 pixels i zoom out a bit in the browser so you can see the page better border one pixel solid black just so we can see what's going on for now i can remove the blue background from canvas on line 8 and on line 21 let's make the border thicker if i change the text i can see it's aligned i set border top to 5 pixels solid block i create a before sudo element this is a special type of element that doesn't exist in html markup and is entirely created with css it has one mandatory property called content we can leave it empty or put some text in here i put down for example is awesome because javascript is awesome isn't it you can see it puts the text before the actual title text like this i want to move it around so i give it position absolute bottom minus 70 pixels font size 40 pixels text align center and width 100 in script js i create a variable called canvas and i set it equal to document.getelementbyid i gave my canvas id of canvas1 so i pass canvas1 here as an argument now we have a reference to html canvas element saved in a javascript variable called canvas now i need to let javascript know if i want to be using 2d or 3d methods so i create another variable called ctx shortcut for context and i set it equal to canvas.getcontext and i pass it 2d as an argument you can see that this canvas is referring to canva's variable from line 1 and i'm passing it 2d as an argument this makes this method return something called canvas rendering context 2d which simply is just an object that comes built-in in every modern browser and this object contains all 2d canvas drawing methods if i wanted to do 3d i would just pass it word webgl instead of 2d here on line 2. if i console.log ctx you can see that it now holds canvas rendering context to the object and if i open that object i can see all of its properties like filter font line width stroke style and so on all of these can be assigned a different value to create different unique effects down here on the object's prototype i can also see all built-in 2d canvas methods that are available for us some of them we will use today like arc method to draw circles or fill style to set color of these circles i will cover the other ones in later videos of the series to show you many awesome effects you can create with this i can remove the console log and now as i said our custom ctx variable contains a reference to this built-in canvas rendering context to the object so if i want to call any of the methods we just saw i call them like this for example ctx.line2 they say everything in javascript is an object and you can certainly see that here where the entire canvas 2d api is just the set of properties and methods on an object let's continue with our effect i set canvas width to window in width and canvas height to window in height i create a led variable called particles array and i set it equal to an empty array like this by using empty square brackets i use led variable here because later on i want to empty this array i will just say particles array equals empty array square brackets if i used cons variable here instead i wouldn't be able to do that because the value of const variable cannot be reassigned i would still be able to change individual elements in the array but i would not be able to reassign it to a completely new empty array that's why i use led here you will see later i create a javascript class which is one of few techniques we can use when we want to create many similar objects in this case i want to create many objects each one will contain data for one particle such as its current x and y coordinates its color and size we will then be updating this data to move particles around and pulling this data out to tell canvas where exactly to draw the particle for each frame of animation let me show you and explain everything step by step now each class has one mandatory method a method is simply just a function attached to an object this mandatory method on javascript es6 class is called a constructor which runs only once per each object in our case once per each particle at the point where we initialize the class by calling it using the new keyword the new keyword is a special command in javascript and it will call particle class and its associated constructor method constructor's only job is to create one new blank object and assign it values and properties based on the blueprint inside the constructor so let's write that blueprint now each constructor will expect two arguments x and y this will be the initial x and y coordinates where the particle first appears on canvas before it starts moving they will be calculated outside as i will show you in a minute so i have to pass them as arguments like this now i say this dot x is equal to x it's a bit weird syntax but also very simple all i'm saying here in the blueprint is telling the constructor x property on this new blank particle object you are creating will be equal to x variable that was passed as an argument on line 8 that's all i do the same thing for this dot y vertical coordinate we will also have other properties on each particle such as this dot size which will determine how big each particle circle is since this value will be randomized internally here inside the constructor blueprint i do not have to pass it as an argument on line 8 because it is not coming from the outside size property on each particle will be created and randomized here inside the constructor on line 11. at first i will make all the particles the same size let's say 10 but if i call math.random times 10 here for example each particle created by this constructor will have a random size between 0 and 10. we will do just that but a little bit later this dot weight will determine how heavy the particles are and this will affect how fast they fall and also how high they bounce when they collide with something i will set it initially to 2 but we could also randomize this value so each particle behaves a bit differently this direction x will be force pushing on particles along horizontal x axis so if i set it to 1 particles will be pushed slightly to the right you will see it in a minute when we draw our first particle i will show you what all of these values do let's take it step by step to make sure we understand what's going on so this is our blueprint whenever we call new particle javascript will invoke class constructor on line 8 create one new blank object and give it values and properties based on the blueprint we just declared between lines 9 and 13. each particle will also have access to custom method i call for example update the job of this method will be to calculate and update particles position for every frame of animation each particle has a weight property as we declared in constructor blueprint on line 12. i want particles to get heavier the longer they fall which will create interesting movement trail especially if they are being pushed to the side by wind at the same time this is also important when you want to make particles bounds i will show you how exactly it works in a minute so here i say for every frame of animation increase particles weight by a very small amount the longer they fall the heavier they get at the same time i want particles to move down so i have to update their vertical y coordinate for every frame of animation increase particle's vertical y position by particle's weight if particle's weight is 1 for example it will move one pixel down for every animation loop we will create animation loop in a minute so here particles are getting heavier and their weight is being added to their vertical y position each particle will also need a custom draw method the job of this method is to take values like position x and position y and size and draw a circle there representing our particle here i will be using all belfan canvas 2d api methods we invoked on line 2 if you remember by calling canvas.getcontext2d and saving it as a reference in a variable i called cdx that's why all canvas 2d methods are now available on my ctx variable and i can call them like this ctx fill style determines fill color of canvas drawings i will set it to red don't forget to put the color in quotes when you draw a circle on canvas it's different than drawing a rectangle rectangle is a shape but circle on canvas is considered a path similar to when you draw a line so to draw a circle first i need to call beginpath which will tell javascript we want to start drawing now i can call built-in canvas arc method which takes at least five arguments we need to pass it all these arguments so that javascript knows where we want to draw our shape it expects position on the horizontal x-axis so i pass it this dot x from line 9 position on vertical y axis will come from our blueprint as well from this dot y on line 10. now we need to give it radius which will determine how big our particle is i pass it this dot size from line 10. we are drawing a circular path so now we need to tell javascript where long circle path area we want to start our circle shape at what angle i will start at angle 0 so i pass it 0 as start angle argument and as end angle i pass it mass of pi times 2 which is a value in radians that converts exactly into 360 degrees and some of you might know that 360 degrees is a full circle if we pass a different start angle and end angle values we can draw a half circle shape or many other shapes here as well but today we want our particles to have a shape of a full circle when i'm done drawing i call close path and i call built-in fill method to fill our circular path with red color i need to call all of these methods from our custom ctx variable so this is our particle class which we can now call anytime using the new keyword and it will create one new blank particle object and assign it properties and values as declared in particle class constructor between lines 8 and 13. every particle object we created this way will also have access to update method which will calculate particle movement for each frame of animation and each particle will also have access to draw method which will take information like updated position and size and it will draw a circle there representing our particle now that we have our class we can try and create the first particle i create a constant variable i call for example particle 1 and i set it equal to new particle the new keyword is a special command in javascript and it will make javascript jump up to line 8 and call javascript class constructor create one new blank object and assign it values and properties as declared between lines 9 and 13. on line 8 you can see our particle class constructor expects two arguments x and y which will determine position on x and y axis where the particle appears when it's first created before it starts moving falling down in our case so here i pass it 100 as x coordinate and 10 as y-coordinate the last thing we need is a for loop that will draw our canvas over and over again i create a custom function i call for example animate its job will be to call everything that needs to run for every animation frame it will be calling it over and over creating our animation loop let me show you for every frame of animation i want to take particle 1 we just created online 27 and since it was created using our particle class it has access to all associated class methods declared on that class in this case update and draw so for every frame of animation i call update from line 15 which will make particle heavier and it will animate it down along vertical y axis as declared on line 17. i will also call custom draw method from line 19 which will take these updated x and y coordinates from particle object and it will draw a circle there representing our particle i can create set interval for example to run this animate function over and over but there is much better way to create animation loop by using built-in request animation frame method this method is very simple it just runs once and does one thing it simply just calls function we pass it as an argument it calls it just once and then it stops so here i say request animation frame and i pass it animate the name of its parent function from line 29 this will cause animate to run all its code on lines 30 and 31 and when it reaches line 32 it will just call itself again creating our animation loop through a program in principle called recursion request animation frame is optimized and it will adjust frame rate to your screen refresh rate so it's recommended to use overset interval we have just declared animate all i have to do now is to call it by saying animate and brackets like this this will kick off our animation loop yes so we have a particle falling down it leaves a very long trail because we are not clearing canvas from old paint we can either clear all of the old paint so we will just see one red circle moving around but for this effect i want particles to leave fading trails behind so instead of clearing the entire canvas from old paint after every animation frame i will just use a semi-transparent rectangle that will be overlaying the canvas over and over this will create an illusion of slowly disappearing paint as the semi-transparent rectangle layers itself over and over on top of the old canvas paint to do that i just set fill style to rgba 255 255 255 which is white color and the last attribute is for alpha opacity it will be 0.0.1 very low opacity with the fill style declared i use built-in fill rectangle method and i want this rectangle to be the exact same size of our entire canvas covering the canvas with semi-transparent rectangle over and over for every animation loop you see it makes the trail slowly fade away click the like button please if you're getting any value from my tutorials now back to the video on line 27 i can change value for x and y to make particle appear at different coordinates we have a problem when the particle falls down it never comes back again to fix that here on line 16 inside update method i create an if statement it will check if this.y is more than canvas height which means if particle has fallen past the bottom edge of canvas if it did i just set its vertical y coordinate to 0 minus this dot size which will hide the particle just behind the top edge of canvas you can see it resets now you might also notice it's falling faster and faster because here on line 17 we say for every frame increase its weight by a small amount this will add up over time and make the particle fall very fast too fast actually to fix that here inside if statement every time particle falls below the bottom edge of canvas reset its weight back to the original value which was 2. another thing you might notice is that particle follows the same path over and over i would like it to fall from random point every time it falls off screen so i set its horizontal x-coordinate to a random number between zero and canvas width now the particle falls from random points all over the canvas great on line 13 i declared a variable i call direction x and i set it equal to 1. this will simulate wind that pushes on particles horizontally it will push on them at the same time as they are being pulled down by weight variable which represents gravity so we will have both wind and gravity forces affecting particle movement on line 23 inside update method i say for every frame of animation add particles direction x property to its horizontal x position let's make direction x a negative number on line 13 so particles get pushed to the left you can see we get slightly curved path because we have a wind coming from the left and gravity pulling down and because particle is getting heavier the longer it falls as specified on line 21 gravity is becoming stronger than wind over time giving us a curved movement path if i change this.weight on line 12 it will make particles fall faster on line 21 i can also change how fast particle's weight increases for every animation step on line 33 we created particle 1. let's go ahead and create one more i will call it particle 2. i use new keyword again to invoke another instance of our particle class which we'll call class constructor create one new blank object and i can pass it different starting coordinates by giving it arguments for x and y for example hundred and hundred the other properties on this particle two like size and weight will be assigned based on the rules we specified inside constructor earlier on lines 40 and 41 i am calling draw and update methods for particle 1. i also need to call these methods for particle 2 like this online 34 i make sure i name it particle 2 and now we have two falling particles both created by the same class constructor and both have access to shared update and draw class methods so this is how you use javascript es6 classes to create many similar objects as you can see our particles are similar they have the same set of properties and can access the same methods but some of these properties can have different values for example each particle has different x and y coordinates it can also have different size and color but overall they are similar in structure and behavior this is what they mean when they say use javascript classes to create many similar objects let's take it to the next level what if i want to create 300 particles using javascript class i could create each particle one by one like we did create particle 1 and particle 2 on lines 33 and 34 and then i would have to call update and draw for each of them individually like we did between lines 40 and 43 but that would be a lot of repetition that's not a very good way to do things lucky for us javascript has loops and we can use a power of for loop to declare all of this once and tell the for loop to repeat it 300 times to create 300 particles up here on line 6 i create a variable i call number of particles and i set it equal to 300. on line 22 i adjust weight to make particles fall a bit slower on line 34 i create a new custom function called init its job will be to run a for loop and fill particle array we declared on line 5 with 300 randomized particles using our particle class constructor inside init i create a for loop this will run 300 times because i set number of particles to 300 i can delete particle 1 and particle 2 because we will create many more now i want all new particle objects to be stored in particle array we declared on line 5. so here inside for loop that will run 300 times each time it runs i target particles array and call built in array push method this method just takes whatever we pass to it in brackets and pushes it at the end of array we call it on in this case particles array so i pass it new particle which as we explain will call particle class constructor and create one new blank object and give it properties and values based on constructor blueprint we wrote earlier in our case these properties are size weight and so on we also know our particle class constructor expects two arguments for x and y i can just pass some number here but that would mean all particles appear at the same point in the same location coordinates i would prefer if each particle appeared at randomized position all around the canvas so i create a temporary variable i call x its only job is to create a random number so i can pass it as x coordinate to class constructor on line of 37. i say const x is equal to random number between 0 and canvas width i do the same for vertical y-coordinate y is a random number between zero and canvas height so these two x and y variables will just randomize coordinates for each particle and we pass them to new particle on line 38. that's it really since this for loop runs 300 times it will create 300 randomized particles for us i can console particles array to see if it worked to run custom init function and to fill particles array with 300 randomized particles i need to call init like this init brackets i open google chrome console and i can check if you are controlling particles array correctly i can see we have an error here on line 49 that is because i'm trying to call update and draw on particle 1 and particle 2 but these objects don't exist anymore i deleted them so i delete this code as well and i can see particles array in console and it contains 300 particle objects perfect now all i have to do is create a for loop that will cycle through these 300 particles one by one and it will call their associated update and draw methods inside animation loop on line 47 i create a for loop it will run as many times as many particles we have in particles array as long as i is less than particles array length inside i refer to each individual particle in that array using i which stands for index so particles array square brackets i is taken from the for loop so it's zero then one then two all the way to three hundred so particles array i is the first second third element in the array and so on as the for loop runs and i variable on line 47 increases up to 300. for each particle in the array i call its update method to apply forces and calculate its new x and y position then i call draw to take these values and draw a circle there here we go we are using javascript class to create 300 animated particles and we are applying gravity and wind on them on line 20 inside update method we have an if statement that checks if particle has fallen off screen and if it has it resets it i want to reset its horizontal x position a little bit more to the right so we don't have the big empty area in the bottom right corner here i say reset its x position to be a random number between 0 and canvas width times 1.2 1.3 maybe it will spread particle circles slightly to the right all particles are the same size on line 12 i can set this dot size to a random number between 1 and 16. that looks a bit more interesting on line 13 we give each particle base weight of 2. on line 22 we increase this weight value slightly the longer the particle falls and on line 23 we add this ever increase in weight to particles horizontal y position which simulates gravity force let's make particles fall at different speeds by randomizing this dot weight on line 13. i can for example set it to random number between 1 and 2. that's very subtle how about a random number between 1 and 6 interesting let's do a random number between 1 and 2 for now on line 27 i change fill style to orange right or maybe green how about purple i forgot about one thing we are resetting weight whenever particle falls off screen so to keep our randomized weight values i also have to add math.random here on line 90. now we can see some particles fall slightly faster than others it will also affect how high particles bounce when we set up collision detection with text field as i showed off in the beginning of the video if i change value here on line 22 wind might be stronger than gravity and particles start moving more horizontally in index html on line 11 we created h1 title element with text that says javascript let's make particles bounce when they collide with that text i covered everything slowly step by step so far i will also explain everything i do now but we are moving into a slightly more advanced territory so if you are a complete javascript beginner maybe watch this next part twice to make sure you understand what's happening if you want of course first i will target element with an id of title 1 by getelementbyid and i save it in a variable i call title element i create another variable called title measurements and here we will use special built-in javascript method called getboundingclientrectangle it returns an object that contains the size of an element and its position relative to the viewport relative to the browser window that object is now being held in our custom title measurements variable so if i console log it i can see we have all details about title element such as bottom position height left position and so on perfect if i go to style css and i change these values for example distance from top now if i go back to browser and refresh the page to run the measurements again i can see it updated top position on our object back in script js on line 11 i can delete the console.log and i create a custom variable i call for example title i set it equal to a javascript object to run collision detection between particles and this title element i will need its x and y coordinates i will also need its width and height i get all of these values from title measurements variable position on the horizontal x-axis will be its left property distance from the left edge vertical y position will be its top property width is equal to title measurements width and height is title measurement's height so now we have successfully converted html elements bounding box into a javascript object we can use these values from that object to draw that bounding box on canvas inside animate function on line 62 i call built-in canvas fill rectangle method which takes four arguments and draws a rectangle it expects x-coordinate so that will be title.x y-coordinate is title.y same goes for width and height and if i refresh i can see we are drawing a rectangle on canvas that matches bounding box of html h1 title element i will use this as a reference to calculate collision detection between this rectangle and every individual particle one thing i will adjust is the height because i don't want particles to bounce off from this right edge so i will reduce height to let's say 10 pixels on line 61 i can delete the rectangle that represents collision detection area for title element i still have its values stored in custom title object so i will use these values to check if particles and title are colliding inside update method on line 36 i will check for collision between each particle and title element i create an if statement and use common collision detection formula between two rectangles let's pretend particles are not circles but rectangles today it will work and it will look good it's also much easier to calculate to check if title and particle are collide in i need to check four things this might be a bit complicated if you are a complete beginner but don't worry it will make more sense to you if you use it more than once we are entering advanced territory so don't feel bad if you get a bit lost here i will try to help you understand as much as i can in the first of our four collision detection checks i need to see if this particles x is less than title x plus title width the second thing i check is if particles x plus particle's size is less than title x these two checks combined determine whether or not particle and title intersect on horizontal x-axis we are checking if particle is on the same x position as title just horizontally now it could still be below or above the title so we don't know if they intersect just yet to be sure we also need to check if particle and title collide vertically so i do the same thing for vertical y axis i check if this particle's y is less than title y plus title height which means in other words is the particle higher than bottom edge of title rectangle at the same time i also check if particle's y position plus this particle size is more than title y or in other words is particle's y position below title's top edge notice that for all of these four statements i use double ampersand so it means all of these conditions need to be true for collision to be true on line 38 i check if particle's horizontal x position is less than title's right edge on line 39 i check if particle's horizontal x position is more than title's left edge on line 40 i check if particle's vertical position is less than title's bottom edge and finally on line 41 i check if particle's current vertical y position is more than title's top edge if all of these are true we know that particle is colliding with title element we will enter if statement and here i want to make particle move just 3 pixels up in minus direction on vertical y axis if it hits title element you can see that particles slide a bit to the left but eventually they fall through the title that is because on line 32 i am increasing weight over and over and on line 33 i am adding that ever increase in weight to particles horizontal y position eventually weight will be so much so it will just push particles through if i want particles to bounce when they collide with the title all i have to do is to multiply this.weight times minus 0.5 what that does is let's say particle's current weight is 6 when it collides with title by multiplying its weight times minus 0.5 it will convert it from plus 6 to -3 making the particle bounce and move in the opposite direction at the same time that -3 value is still being affected by line 32 where we are adding plus 0.0.1 to particles weight so eventually it will go back to 0 and it will start increasing into positive numbers because particle's current weight is constantly being added to particles vertical position on line 33 this will cause particle to bounce up then slow down when its weight reaches zero and start falling down again as its weight property grows into positive numbers again because of line 32. you can change how high the particles bounce by changing value here on line 44. now you know how bouncing movement works on canvas if you are a beginner and you manage to code along to this point well done this is not beginner stuff anymore great job up on line 6 i can change number of particles to let's say a thousand we have a small problem that comes with any html canvas project when you stretch or resize browser window the entire canvas drawing stretches like this you can also see that it distorts the collision detection area and particles now don't bounce from the correct positions to prevent this from happening there's an easy fix i create an event listener javascript event listener expects two arguments type of event to listen for and callback function to run whenever that particular event occurs we will be listening for a window resize event and when user resizes browser window i will run the following code we will measure the canvas again and set canvas width to window in width and canvas height to window in a height i will also call our custom init function we declared on line 55. i adjusted a little bit by making sure particles array is always empty before this function runs so now whenever window resize event occurs our custom init function will delete all particles from particles array it will run a for loop again and create completely new set of randomized particles depending on new canvas width and height dimensions well done resizing the window doesn't stretch our drawing anymore but we can see that title collision area still gets distorted that's also easy to fix i take title measurement variable notice that i am not using a variable keyword just variable name which means i am taking the same variable and reassigning it different values if i used var let or const here i would be declaring a new variable we don't want that so i reassign our existing title measurements variable by selecting title element variable that holds reference to title html element and i'm calling bounding rectangle again this will just measure position of title element relative to browser window again after we resize the window now i take title object we declared on line 11. notice i also don't use var const or led here so i'm not creating a new variable just updating existing one i can actually go up here on line 11 and just copy all these values like this now every time we resize window we recalculate canvas width and height on line 78 and 79 we measure title element again on line 80 we take these values from line 80 and update existing title object from line 11 here on lines 82 and 85 and lastly we run init function which will delete all current particles and create a set of completely new ones and spread them randomly around the new resized canvas area all fixed ok challenge time the first one is for the beginners are you able to change the direction from which the wind is blowing to do that you would have to change value on direction x property if you're more advanced are you able to change color of particles to look like this i covered how to work with canvas gradients in my previous video if you want to learn more i will leave a link in the video description thank you very much for watching don't forget to click the like if you like my stuff and want me to make more subscribe and hit the bell icon to get notification when i release another creative coding tutorial while you're here you can also check out some of my other creative coding tutorials see you next time [Music] you
Info
Channel: Franks laboratory
Views: 16,960
Rating: undefined out of 5
Keywords: JavaScript project tutorial for beginners, HTML Canvas Particles, JavaScript project, JavaScript tutorial, avaScript project for beginners, JavaScript tutorial for beginners, JavaScript for beginners, HTML Canvas project, HTML Canvas tutorial, HTML Canvas tutorial for beginners, HTML Canvas for beginners, Basic Javascript Projects, JavaScript Project Tutorials, Build JavaScript projects, vanilla JavaScript course, franks laboratory, frankslaboratory, javascript, html, css
Id: nrJh8-Ixnu8
Channel Id: undefined
Length: 40min 54sec (2454 seconds)
Published: Fri Sep 04 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.