Vanilla JavaScript Text Animation Tutorial [Particles & Physics effect]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

After Effects has some interesting text animations for motion graphic titles. I've considered trying to replicate them in Processing but it would be quite challenging.

👍︎︎ 2 👤︎︎ u/webauteur 📅︎︎ Aug 08 2020 🗫︎ replies

Um isn't this sub for processing/p5 projects/help, not native js? It's really cool, just not really the right sub

👍︎︎ 1 👤︎︎ u/Pythag0ras2000 📅︎︎ Aug 08 2020 🗫︎ replies
Captions
in today's vanilla javascript text animation tutorial we will learn how to take any word letter or sentence and in three steps to convert it into interactive particles effect we will learn how to give particles some motion physics and apply forces such as friction and acceleration then we will get the particles to form any shape we want in this case letter shapes and connect individual particles with lines similar to famous particles.js library but we will use no libraries everything we built today is from scratch using just plain vanilla javascript i will explain all the code line by line as i always do hi coders welcome to my creative javascript series where we combine art with code have fun building games from scratch and learn front-end web development techniques in the process this video is special for me because it's been exactly one year since i started my channel as a celebration i will take two of my most popular tutorials i have made for you so far tweak them a little and combine them into particle text animation you can see right now don't worry if you didn't watch these videos as usual we will build everything from scratch using just plain vanilla javascript and i will explain every line of code as we go along coding section will have three main parts in the first part we will just create particles randomly spread around the canvas and we implement some physics on them we will apply forces like friction and acceleration and give each particle different weight to make the movement more realistic then in the second part of this video we will take these particles and shape them into letters or images both is possible with the code we will build today and lastly in the third section we will take the famous constellations effect from particles.js library and we will connect particles that are near enough to each other with lines but we will not use any libraries we will write our own vanilla javascript code that does that i just want to say well done because if you are watching a video like this you are already ahead of so many people you could be watching a sitcom right now which is fun as well but you are here learning new things which means to me you are serious about developing your skills i just wanted to say this because staying motivated on your learning journey is the single most important thing so don't give up and keep pushing forward now let's talk about javascript two of my videos that people seem to like the most are converting images into interactive particles and constellations effect from particles.js library but built from scratch with no libraries i took parts of code from both of these tutorials greatly improved mouse interaction movement by adding some physics and created this text animation effect you can make it into animated logo for your website interactive background automatic loading animation and many more this is creative coding unlimited possibilities you can use it for your coding portfolio to impress potential employers or just as a coding exercise to practice your vanilla javascript and front-end web development coding skills let's take a closer look at the effect we are building today we will write text on canvas filter out certain pixels depending on their color or opacity and convert coordinates of these selected pixels into particles we will use array manipulation to store these particles as data and using javascript es6 classes we create a custom set of particle objects for our animated effect once we have that we can do whatever we want with them by giving them behavior using class methods so i will make them interact with mouse and connect particles that are close enough to each other with lines if you want to learn more about constructor functions es6 classes this keyword and get a complete comprehensive look about object oriented programming in javascript which is helpful for many particle effects we create here on the channel there are some udemy courses that really stand out for me i will leave a link in the video description in case you are interested if this is your first time here hi my name is frank and i'm a self-taught front-end web developer i learned everything i know in my free time from youtube and online courses how about you i'm really wondering what kind of programmers are interested in creative coding videos like this do you study coding in school are you a self-taught programmer or do you work as a professional developer how long have you been learning html css and javascript are you getting ready to apply for your first coding job or do you still feel you need more time to learn before you are ready or if you are more experienced what kind of advice would you give to people who are just starting with javascript and front and web development in general let me know in the comments i want to know more about you guys if you watch the video and code along with me at the end i will show you how to create some interesting variations of this effect or maybe i will give you a hint and make it into a competition let's see also click the like please if you're getting any value for my tutorials let's start coding in index.html i link css stylesheet create html5 canvas element with an id of canvas1 and ilinkscript.js file which will contain all javascript logic in style css i just do the basic reset to make sure the page appears the same in all browsers ask the risk selector to target all elements on the page and i set margin to 0 padding 0 and book size into border books body box means that elements padding and border will be included in its total width and height on the body element i set overflow to hidden to hide potential scroll bars and give it black background i choose to place the background on the body element instead on the canvas because this will allow us to use liquid or distortion svg filters if we choose to especially liquid filter only works if canvas background is transparent canvas will have position absolute job 0 left 0 everything else will be done with the javascript in script.js file i create a variable i call canvas and i set it equal to document getelementbyid canvas1 ctx shortcut for context is equal to canvasgetcontext2d doing this will create a built-in context object that contains all kinds of 2d drawing methods that come built in in any browser using canvas api now i can call all of them using our ctx variable canvas width is a window in a width and canvas height is window in a height this will make sure the canvas covers the entire browser window i create a variable called particle array and i set it equal to an empty array this will contain all our particle objects that each contains information like size color and coordinates and we will pull this information from here to draw them on canvas before we do that i will write some code to handle mouse interactions i create a custom variable i call for example mouse and i set it equal to javascript object by using curly brackets like this i give this custom object some properties x will be the current position of mouse on horizontal x-axis y will be positioned on the vertical y-axis radius will be size of a circle area around the mouse within which the particles react to mouse i create an event listener it takes two attributes type of event to listen for and callback function to run every time that particular event occurs i want to listen for mousemove event and every time user moves the mouse within the browser window i want to run the following code callback function on event listener has one special thing about it it has access to built-in object that contains all different details about the event that is occurring all i need here are x and y coordinates of the event so that i can assign them dynamically to our customer mouse object i created on line 8. i need to assign them to the custom object to pull that coordinate information outside of event listener so i can use this information all over our application so as an argument to the callback function i write down event some people just put letter e here it doesn't really matter javascript knows this variable will stand for that built-in event object and will let you use it whatever you call it here as long as you refer to it using the same variable name later on so inside the callback function i set mousex which is property declared on line 9 to event dot x and mouse y to event dot y if you console.log event inside this event listener you will notice it is quite similar to our custom mouse object on line 9. the only difference is that it contains many more properties and it is only available inside an event listener that's why i am pulling the information from it here and sending it outside to our customer mouse object so that mouse coordinates are available all over our application wherever i might need them later on i can check if it works by console login mouse x and mouse y now if i move mouse over the canvas with open console i can see we are getting values great this is one of my favorite ways to handle mouse input it is useful for everything from generative art website interactions to games now let's draw some text on canvas ctx font properties sets the current font properties for text context on the canvas you can also set bold or italic here if you want then you put size and the last attribute will be font family let's just try 30 pixels verdana for start now i call ctx fill text method which will just draw and fill text on canvas it expects at least three attributes the first one is the text we want to write i just put capital letter a for now the second one is x coordinate on canvas where you want to draw that text the third attribute is y-coordinate there is also an optional fourth attribute where you can define max width of the text in pixels we will leave it empty for now but keep that in mind by default the text will be black unless you set it to any other color using fill style property so i call ctx fill style method and set it to white now we can see we are drawing our text at specified coordinates i can change it by adjusting its size on line 21 or its position on line 22. now what i want to do is to scan a small area of canvas around the white letter a analyze the pixels filter out pixels with no opacity because that's where the text is and only save those pixels that are not transparent into our particles array more specifically i want to save their x and y coordinates and i can also save their color values if i want to that way we can replicate the shape of letter with particles by using x and y coordinates of each pixel as coordinates for our particles remember that the black background is on body element so canvas is completely transparent with only letter a having white color to do this i just use another canvas method called get image data we used it before to turn image into particles in one of my all-time most popular videos and we will do something similar today with text official definition of this method is that it returns image data object representing the underlying pixel data of a specified portion of the canvas if i want to say it much simpler you give this method four coordinates for rectangular area somewhere on canvas it scans that area pixel by pixel and it saves coordinates and color information for each pixel inside of a huge data array since we know how the data is organized we can easily extract that information and use it for anything we want so i create a variable i call for example data and i set it equal to ctx dot get image data and i pass it for attributes to tell it what part of canvas we want to scan i want to start from top left corner so coordinate 0 0 and i want to scan just small bit let's say square of 100 times 100 pixels so i pass it with 100 height 100 which is somewhere around here if i want to visualize the area we scanned i can just stroke white rectangle there so we can see stroke style set to white stroke rectangle and i pass it the same area i passed to get image data method on line 25 see this is the area we will be scanning so our data variable on line 25 will contain array with coordinates and color information for each pixel inside this small square okay let's delete this it was just so we can visualize what's going on now i need a way to create many similar particles that will each represent one interactive dot in our final effect for that i will use javascript class i call it particle with capital p each class has one mandatory method called a constructor constructor will run just once for each particle it will create a new blank object and assign it properties and values based on information i will declare inside of it it will serve as a blueprint our constructor will expect just two attributes x and y coordinates which will be different for each particle and we will pass them to the constructor from the outside to make it spell out our letters for the final effect inside i just say this dot x property on a new blank object you are creating is equal to x we passed as an attribute same for vertical y coordinate we will have other properties but these will be set or randomized here inside the constructor we don't need to add them from the outside so we don't need to pass them as arguments on line 26 this dot size will be radius of each circle particle so let's try for example 3 pixels i will also set this to base x and set it to this dot x and this dot base y and set it to this dot y base x and base y properties will hold the initial position for each particle from the first time they appeared the reason for that is that we will be moving and pushing the particles around by changing their this.x and this.y properties but i want each particle to remember where it came from so it can return to its original position when mouse interaction ends also i choose to set this dot base x equal to this dot x property from line 27 instead of setting it to x attribute passed on line 26 it will be the same but doing this will allow me to modify the starting position of this dot x on line 27 like this and our base x variable will remember that modified state it can be used for interesting distortion effects not sure if we do it today but there is no harm if we set up our code base for it anyway this low density will be a random number between 1 and 30. it will determine how heavy our particles are and how fast they move away from the mouse i want each particle to move slightly different speed to simulate some physics so now the blueprint is complete we will also need a custom draw method each of our particles will have access to it because it will be sitting on the particle class this method will just take x and y and radius from the constructor and draw a circle there representing our particle i set fill style to white we are drawing a circle on canvas so i need to use ctx begin path method think of it as pencil touching down on canvas to start drawing i call canvas arc method and i pass it this dot x and this dot y coordinates this dot size will be radius of the circle start angle will be 0 and end angle will be math.pi times 2 which is value in radians that represents that actually converts to 360 degrees so we have just drawn a circular path from 0 to 360 degrees which is a full circle if you change start angle and end angle values here you can use arc method to create half circle or even many other shapes i call close path and ctx fill to fill the path with white color now i create another custom function i call init its job is to take particle class we just created and call it many times the fill particle array with randomized particle objects first i will set particle array to an empty array in case it's not empty at the moment now i call push method which will take whatever we pass to it and pushes that to the end of the array we call it on i pass it new particle the new keyword is a special command in javascript it will call constructor of its associated class in our case it will go up to line 26 create one new blank object and give it values and properties as described in the blueprint between lines 27 and 32. on the line 26 we can see our constructor expects x and y coordinates as attributes so here on line 45 i pass it 50 50 as coordinates for now now i call init to push one particle into the array i can't lock particle array to see if it works i need to comment outline 17 that's still log in our mouse position yes now i can see the array contains one particle i can add another one at coordinates 80 and 50. and now we have two particles in our array i create a custom function i call animate which will handle animation loop first i call ctx clear rectangle and pass it canvas dimensions to clear the entire canvas between every frame of animation i create a for loop that will cycle through the entire particles array and for each particle object inside that array it will call its custom draw method we declared on line 34. the last thing i need to do is to call request animation frame and pass it animate the name of its parent function this way animate will run all of its code and it will call itself again over and over create an animation loop through a program and principle called recursion so far i have just declared animate i also need to call it to start our animation loop it is not drawing our particles and in console i can see we have error on line 37 where i misspelled arc fixed now we are drawing two particles as i declare them on line 45 and 46 i can change their x and y coordinates and you can see they will move around as i change these values so instead of calling the particles individually like this i create a for loop that will run for example 10 times i comment out the two individual particles and inside the for loop i do the same thing particle array push and i pass it new particle it expects x and y coordinates so i will create a temporary x variable its only job is to generate random number between 0 and 500. do the same for y coordinate now i call new particle and i pass it temporary x and y variables i have just created on line 46 and 47. you can see we are drawing 10 randomized particles because for loop on line 45 runs 10 times if i want the particles to be randomly spread all around the canvas i can set x to a random number between 0 and canvas width and temporary y variable to a random number between zero and canvas height now our entire canvas is covered with particles i increase the amount of particles to let's try 500 well done we have base structure for our generative art project in place first we declare global variables then created object to store mouse coordinates then on line 25 we create a blueprint that will be used to create particles function init online 43 will use that blueprint to fill particle array with particle objects and lastly we created animation loop on line 56 which is running over and over and redrawing our canvas for every frame even though it looks static now we are actually drawing the same thing over and over let's make it move now on line 35 i can change color let's try red i create another custom method i call update its job is to calculate distance between current mouse position and current particle position if they are close enough i want particles to be pushed away from the mouse now i will show you how to calculate the distance between two points this can be used for creative coding and it is also very useful for games let's calculate distance between two points on horizontal x-axis first i will call this variable dx it is simply the difference between their position on x axis let's say if mouse position x was 50 and particle position x was 30 dx will be 50 minus 30 which is 20. simple it's just the difference same for dui which is the difference between position of two elements we are comparing vertically we are comparing mouse against all particles one by one so d y is mouse dot y minus this dot y this dot y stands for each individual particle as we cycle through all of them one by one imagine these two values we have just calculated create a right angle triangle between mouse and particle we have a dx side we have a d y side of the triangle and we know there is a right angle between them so 90 degrees we can get distance between these two points by calculating the longest side of the triangle opposite to the right angle it is also called hypotenuse there is a built-in method hypotenuse method in javascript but today i will just use pythagoras theorem to calculate it we have two sides of right angle triangle and we know there is a 90 degree angle between them we need to calculate the third side and that will be the distance between two points which is what we need formula is mod square root dx times dx plus dy times d y which also is which is the same thing as math square root dx squared plus d y squared since this is calculated inside update method on particle object each particle will always be aware of how far away it is from a mouse so here i can say if distance between particle and mouse is less than 500 run this code if particles are closer to mouse than 500 i will set their size to 50 pixels else distal size will return back to 3 which is the original value we declared on line 29. to run this code i need to go inside animation loop and on line 68 inside for loop that cycles through the entire particles array for every frame of animation the same way i call draw method for every particle i will also call update the method we have just created and you see it works now i can change the distance particles react to mouse here on line 45 i can also create more particles on line 55. now you can see the distance is being correctly calculated and we have a nice boilerplate for creative particle effect we can do so many things now maybe if you want before we continue you can save and copy this code base in a different folder and experiment with it later on it's always good to have the base setup stored away somewhere and now you can just focus on your experiments so what i want to do now is for particles that are close to mouse to start moving away from it i want them to move from the center point of the circle towards the edge i also want particles to move at different speeds depending on their weight we defined earlier when we assigned this density property inside particle class constructor and third thing i want to happen is for particles to move fast if they are close to mouse but gradually slow down the closer they are to the outer edge of circular interaction area until they reach speed of zero when they touch the outer edge basically we will introduce some basic physics to particle movement this might sound like a complicated thing to do with code but i will show you a nice calculation that can do all of this for us i create a variable i call force direction x and i set it equal to dx divided by distance first direction y will be d y divided by distance on line 48 if particles are closer to the mouse than 300 pixels i will add force direction x to particles current x position and force direction y to particles current y position this will just make them slowly move towards the mouse if i multiply these values by let's say three it will make the movement faster now i want to set a distance past which particle's movement speed is zero so i create another variable i call it max distance it will be equal to mouse.radius we declared on line 11. any particle that is more distant from the current mouse position than this will stop moving this calculation i'm about to do takes any range of numbers and converts it to a range between 1 and 0. it will convert values between 0 and max distance into a range of 1 to 0 just so i can multiply values on line 51 and 52 by this number and get the particles to slow down as the distance between them and mouse increases until they reach speed 0 as they reach the outer radius of interaction's circle around the mouse so i will call that variable for example force all i want to do now is to take number range of 0 to 250 and convert it to number between 1 and 0 depending on where on range between these two values the number is 0 is particle with a distance 0 from the mouse so it will be touching the mouse i want this number to be converted to 1 so i can multiply current particle speed by this which will make the particle move at its full speed the second side of that range is number 250 which is represented by max distance variable i want any particle that are further away from the mouse than this to have speed 0 so they stop moving let's say there is a particle halfway between 0 and 250 so this particle is roughly halfway between these values it is 125 pixels away from the mouse at that point i want that particle to be moving at 50 speed so i need force variable to be equal to 0.5 at that point if i multiply current speed times 0.5 it will move at 50 speed when particle reaches 80 percent towards the outer edge of interaction circle i want it to move at 20 percent speed so i want force to be 0.2 when particle is at 90 percent i want it to be moving only at 10 percent of its original speed and so on to get this behavior i need to convert range between 0 and 250 or whatever max distance variable is on line 48 i want to convert this range to a smaller range between 1 and 0. once i have that value i will multiply it times particle speed and it will cause particles to slow down in proportions to its current distance from the mouse you can already see the calculation i say max distance minus current distance to see how far particle currently is from the max distance area and once i have that value i divide it by max distance again which will tell me what proportion of max distance it is quick example if max distance is 100 pixels and particles current distance from mouse was 20 pixels max distance minus current distance would be 80. then 80 divided by 100 is 0.8 so our force would be 0.8 basically anything multiplied times 0.8 is 20 less so it will slow our particle down by 20 percent i'm not sure if this is just me or this is quite difficult mathematical operation to understand it took me a very long time to work this out i will get back this again and try to explain it better next time we use it let me know in the comments if it's unclear and we can talk about it so now i have the force which is the multiplier that will be slowing particles down as they get further away from the mouse i create a variable called direction x which will combine all factors that play a role in particle's movement speed direction x is equal to force direction x on line 46 times force we just calculated on line 49 times this density from line 33. i add this to density into the mix because i also want individual particles to have different mass and i want that value to affect their movement speed it will look more natural otherwise all particles will move the same speed as particles around it i do the same thing for direction y it will be equal to force direction y from line 47 times force which will cause it to slow down as it moves further away from the mouse times this density which is individual and different for each particle it's a random number between 1 and 31 as we declared on line 33. now on line 53 i say if distance is more than mouse radius which we declared on line 11 this dot x plus equals direction x variable from line 49 which combines all forces that pull and drag on our particle and i do the same thing for particles word and i do the same thing for particles vertical y position this dot y plus equals direction y that was calculated on line 50. it works yay particles move slow at first and speed up as they get closer to the mouse the only problem is that i want them to be pushed away so i change plus sign to a minus sign on lines 53 and 54. yes this is good and this is how you implement quite complex physics with javascript i really like the movement and we will enhance it even further by the word this was the difficult part i'm not sure why i put mouse radius here on line 17 inside mouse move event that's wrong i will just delete that mouse radius is set to 450 pixels on line 11. if you look closely particles move at full speed when they are close to the mouse and when they get close to the outer edge of interaction circle they move slower and slower until they stop i can make the move faster by changing density let's try range between 50 and 200. you can change the movement speed by adjusting the range of values here on line 31. so on line 51 i check if distance between particles and mouse is smaller than a certain number defined in mouse radius if it is i push them away from the mouse as you can see particles stay where they are when mouse interaction ends i would like them to return to their original position so here on line 54 in else statement i say if this dot x is not equal to this dot base x base x is defined on line 29 and it captures the initial position of each particle so if this dot x has changed because we push particles around and it is no longer equal to base x which is particles original position i will calculate distance between this dot x which is particles current position and this dot base x which is particles original position on the horizontal x-axis once i know the difference i can just return particle to its original horizontal position by saying this dot x minus equals dx but to make particles move back slower i say dx divided by 10. it will eventually get to its original position because this code is run for each frame of animation it will just get there slower also keep in mind we are currently inside else statement which will be entered only when particle is not close enough to the mouse so particles will only try to return to their original position once mouse moves far enough from them so this way we corrected particles horizontally we can also correct them vertically notice i don't do else if here i just do simple if statement because i don't want these to be mutually exclusive if particle has been displaced on x-axis and also on y-axis both of these statements will run for each frame of animation but also they can just run separately in case only x-axis or only y-axis position needs to be corrected to return particle to its original position as we saved this original position in base x and base y variables so if this dot y is not equal to this dot base y i calculate the y value distance y value and i adjust this dot y by saying minus equals d y divided by 10. by changing values on line 57 and 61 i can change how fast particles return to their original position so this all works at the moment we are just spreading particles randomly around the entire canvas area by calculating random x and y values here on line 70 and passing them as attributes to particles class constructor on line 72. how do we make the particles spell out letters of text for that we use data variable we declared online 22. here we call canvasgetimagedata inbuild method that takes four attributes for a rectangular area of canvas we want to scan and it returns image data object that contains information like coordinates and color of the pixels from that area on canvas actually let me rename this variable for clarity i rename data to text coordinates so now this variable i called text coordinates holds whatever get image data method returned go down inside our custom init function which at the moment runs a for loop thousand times each time it runs it calculates random x and y position and creates a particle there i delete all this code because we don't want our particles to be randomly distributed around canvas we have just scanned the part of canvas where we drew some text and now i will filter that returned object that resulted from our scan and i will remove all pixels with transparent background leaving only data points for pixels that contain color which will be coordinates for particles that make out our text effect keep in mind that canvas is transparent the black color you see is set on body element so the only pixels with color are the actual letters let's go through it step by step i create a for loop and i will do something a bit weird instead of just declaring one variable here as the first attribute i declare two variables i say let y equal 0 comma y2 equals text coordinates dot height as long as y is less than y2 y plus plus this is almost a normal for loop two things to mention here first yes you can do this in javascript you can put more than one variable inside a for loop also i could have just declared y2 variable outside the for loop and it would work as well second thing is that i say y2 equals text coordinates height text coordinates holds image data object that resulted from a scanning small portion of canvas using getimagedata method this object has height property in pixels and since i want to scan the resultant pixel data line by line in this case row by row i will run this for loop for every row of pixel data we have so we declared two variables and i say as long as y is less than y2 y plus plus don't overthink this we just have two variables y will keep increasing until it reaches the same value as y2 so our for loop will run until that happens so this is analyzing pixels row by row each time i enter row of pixels i want to go through them one by one from left to right so i create a nested for loop which simply is loop inside of another loop here i say let x equal 0 x 2 is text coordinates width which is simply just width of scanned area in pixels in this case we scanned rectangle hundred times 100 pixels as you can see on line 22. so text coordinates height is 100 text coordinates with is 100 as well this outer for loop will run 100 times and each time it runs it will run in a for loop 100 times so we're gonna analyze 100 x 100 10 000 pixels i will explain this further in a minute back on line 70 i say as long as x is less than x 2 x plus plus this nested for loop might look complicated but all that's happening here is i have a grid of 100 times 100 pixels i go through them row by row on line 69 each time i enter one row i go through that row of pixels one by one until i reach the end in this case pixel number 100. in for loop on line 70 will exit we jump back to the outer loop on line 69 y will increase by 1 which will give us another row we enter in a loop on line 70 again and go through all the pixels on that new row from pixel 1 to pixel 100. then we exit the inner loop again enter the outer loop increase y by one which gives us the next row and we do this for all hundred rows analyzing all hundred pixels in each row as i said we have 100 times 100 pixels because that's the area of canvas i have decided to scan using get image data method online 22. this nested loop basically allows us to cycle through every pixels in that hundred times 100 pixel area for each pixel i check if opacity of that pixel is more than 128 i will explain what that means in a second text coordinates custom variable holds built-in image data object that was returned by get image data javascript method this object has built-in data property which is an array of elements that represent pixels from the scanned area of canvas we can look inside by console login text coordinates in the console i can see it holds image data object if i open it you can see that object has a data property and this data property holds data array with 40 000 elements more down you can also see that it has height and width properties set to 100 which are the values we used in the nested for loops don't get scared this is very simple it is not a normal array if you look closely you will see this type of array is called something like uint8 clamped array if i simplify this it's a special type of array that can hold only numbers and those numbers are limited to a certain range you can say they are clamped each element in this array can only be a number between 0 and 255. if you work with html and css you have seen rgba color declaration which looks like this any color can be created by combining different amounts of red green and blue and the range for each color is from 0 to 255 one weird thing about this clamped array is that it also handles alpha or opacity this way so 0 alpha is invisible 255 alpha is fully visible this is different because in rgba color declaration opacity is a small number between 0 and 1. so why does this array have forty thousand elements when the area we are scanning is hundred times hundred pixels and we know hundred times hundred is only ten thousand not forty thousand also remember that this is a special type of array called clamped array so every element it contains can only be a number between 0 and 255. again very simple explanation let's look back at our rgba color declaration each color is made out of four properties red green blue and alpha same with this clamped array data object the way it's organized is every four elements in that array represent these four color values for one pixel so color for pixel one is the first four numbers in this array color for pixel two is the next four numbers and so on that's why we have forty thousand numbers in this array and we only have ten thousand pixels it's because we need four numbers to make one color each number is something between 0 and 255 including the number for alpha opacity that's why online 70 i check if value is more than 128 which would be around 50 opacity it's like halfway between 0 and 255 roughly 50 any pixels with more than 50 opacity will be added to our particle array each one will create a point in the final font shape to extract these values we have our nested for loops if particle passed check here inside if statement i create a temporary variable i call it for example position x and i set it equal to x which is the variable from line 70 and it represents number of pixel in a row that passed our opacity check i do the same for position y which will be equal to y from line 69 which represents a row vertical position of that pixel we are analyzing right now so in terms of x and y coordinates it's a vertical position of pixel that passed our opacity check so i cycle through all pixels i check their opacity value and if their opacity is more than 50 i capture their coordinates in temporary variables position x and position y and i call push on particle array which is my custom array i created to hold particles for my effect push method just takes whatever we pass to it and places it at the end of array so i pass it new particle which we'll call particle class constructor that uses esx class blueprint we created earlier and creates a blank object and assigns it values and properties based on the rules we declared in a blueprint our particular class constructor expects two values to come from the outside for x and y coordinates so i pass it position x and position y variables from lines 72 and 73. remember that this code runs only when opacity is more than 50 so only these particles from the scanned area will be added to our array there is just one more little problem to sort out as i said clamped array that is held in text coordinates data object contains 4 elements for each pixel we have 10 000 pixels but this array has 40 000 elements it holds value for red green blue and alpha for each pixel right now i am just checking one pixel because i passed index 1 in that array inside square brackets here what i want to do is to cycle through the entire data array and take every fourth value because i know every fourth value stands for opacity for each pixel it's always red value green value blue value opacity value and so on so i need to replace one with some code that will allow us to skip three elements check the fourth one skip another three elements check the next one and so on one way to do this is i say in brackets y times four times data with plus x times four plus three remember that we are inside a for loop so y will be one then two then three as we cycle through rows and x will be one two three as for loop cycles through pixels in each individual row this calculation is not very intuitive just know what i'm doing is i'm cycling through 40 000 elements and always skipping three and checking the fourth one i am not a math expert so this took me forever to understand but i think for now it's good enough for us just to show just so you know what i'm doing i'm sure there are simple calculations to lock every fourth item in an array anyway i will explore it more when we use this technique next time that's it this is how you scan portion of canvas filter out pixels with no opacity and save their coordinates in your own data array since the font we scanned is very small as you can see here we don't want our particles to cover this small area we want to spread them out evenly while keeping the shape of our letter a so here on line 74 i just multiply position x times 10 and position y times 10. i made a small mistake on line 71 earlier i renamed data to text coordinates but here i still refer to it as data let me fix that and we are drawing particles in the shape of a letter a well done this is some advanced coding i can change spread of the particles and therefore size of particle text by adjusting values here on line 74. since we are taking particles from certain area and multiplying their coordinates to spread them around it's not that easy to move the text left and right but i can still do that by adding adjustment variable here on line 72 and also on line 73. i call them adjust x and adjust y and up here on line 6 i declare them and let's push x 10 pixels to the right and y 10 pixels down now you can move your particle text shape around anywhere you want by adjusting these two values size of the effect can be changed here on line 76 let me just center it in the middle and of course you can change the text we draw here on line 23. some of you might like this effect already but that's not all i also want to connect particles that are close enough with lines similar to the famous particles.js constellations effect but on a text instead on random floating particles and instead of using a library we will write our code ourselves i create a custom function i call connect its job will be just a cycle through the array of particles that make up our letter and measure distance between each particle if they are close enough we will take coordinates of the first particle and we draw a line to the coordinates of the second particle that's it click the like please if you're getting value from my tutorials so i create a for loop that cycles through the entire particles array since this for loop will have to run for every frame of animation let's optimize it a little bit normally i would just do nested for loops and i would compare every particle to every other particle in the same array but i don't have to do that the inner for loop only needs to cycle through the remaining particles in the array because all the particles before have already been compared in previous cycles of the outer for loop i'm not sure if i'm explaining it clearly but let's write some code and i will try again so in the inner nested for loop instead of cycling through the entire particle array again just so i can compare every particle against every other particle i will only cycle through particles that have higher index than a because anything with lower index has already been compared in previous cycles of the for loop so here i say let b is equal to a as long as b is less than particles array length b plus plus if you look at line 96 again when the outer loop runs for the first time it will cycle through the entire for loop in the outer loop and inside the inner loop as well but eventually when variable a in the outer loop reaches number let's say 50. in the inner loop we say b is equal to a and we cycle only through particles from index 50 to the end of the array this will pair up all individual particles inside particles array all i need to do here is calculate their distance and say if distance is less than some value connect them with a line we have already calculated distance between mouse and particles on line 45 so again it's exactly the same thing dx variable will hold distance between two elements we are comparing on the horizontal x-axis the y variable will hold distance between two points in this case between particle a and particle b on vertical y axis this will give us two sides of right triangle and we know that the distance between these two points is hypotenuse the longest side of the right triangle the side that is opposite to the right angle to calculate it we can use pythagoras theorem formula which we learned in school a long time ago math square root from dx squared plus d y squared or in other words math square root from d x times d x plus d y times d y so to calculate d x distance of two particles on the x axis i say particle array a x minus particle array b x a and b variables will be changing as we cycle through both for loops so this code will compare every particle against every other particle by the time the for loop has finished d y will be particles array a y minus particles array b y now we have two sides of imaginary right triangle and all we need to do to get distance between these two particles is to calculate hypotenuse so math square root dx squared plus d y squared now i can say if distance is less than 100 pixels i set stroke style to white because we want white lines line width will be 2 pixels for example on canvas line is the same as arc we used to draw circle it is considered to be a path so to start drawing i will have to call begin path to draw a line on canvas you need to call move2 method to set starting x and y coordinates and line 2 method to set target x and y coordinates when you do that a line will be drawn between these two points each point defined by two coordinates x and y so at first i call ctx move2 method which creates a starting point of a new path at coordinates we passed to it we are inside an if statement that only runs when two particles are close enough to each other so i just want to draw a line from one particle to another the starting point of the line will be x and y coordinates of particle a that passed our distance check then i call a line two inbuilt canvas method this method simply said creates a straight line from coordinates we pass to it to the last previous point inside the same path start and end of path on canvas will be defined by begin path and close path method calls here so i call line 2 and i pass it x and y coordinates of particle b that passed the distance check now that you can understand how parts and lines work you might be able to see that we can keep drawing more and more parts like this and create custom complex shapes but i only want to draw a single line connecting particle a and particle b all you need to do to create the popular particles.js constellations effect with vanilla javascript is this code we just wrote from line 94 inside our custom connect function we have just declared a function we also need to call it inside our animation loop to actually run the code so on line 90 i call connect and here we go this is just the basic effect we can make it a little bit nicer than this here on line 105 you can change the distance limit the limit will determine maximum distance between particles that get connected by white line i think 50 looks pretty good but for you it might be slightly different number depending on your base font and how much you decided to scale your particle shape earlier just try different numbers here and see what you like one important visual thing that particles.js library does is that the lines are not always fully visible they don't just appear and disappear as particles move closer and away from each other lines slowly fade away and slowly appear again basically opacity of the lines is dynamically calculated based on the distance between particles it looks much cleaner that way to do this in our custom code base is very simple on line 96 i create a new variable called opacity value and initially i set it to 1 full visibility then here on line 107 i set stroke style to rgba color declaration rgb value for white is 255 255 255 and i will concatenate opacity value variable as the last fourth attribute for opacity like this now we have a variable that can dynamically change and opacity of lines will change with it to make opacity proportionate to the current distance between particle a and particle b i run this strange formula basically what i want is if distance is close to zero particles are very close to each other so i want opacity to be close to one as the distance between particles increases i want to decrease the opacity value until particles are far enough and opacity will be zero there are many ways to do this simple way is to say 1 which is full opacity full visibility so lines are visible minus distance divided by 50. notice that i divided by the same number don't overthink this let me give you two examples if distance is zero particles are close line is fully visible on the other hand if distance is 50 1 minus 50 divided by 50 is 1 minus 1 so 0 lines are invisible when the distance between particle a and particle b reaches 50 or whatever you set the limit to if you want particles to have zero opacity when they reach maximum distance keep these two numbers on lines 106 and 107 the same if you change distance to 100 change the formula on line 107 200 as well and the effect will work the same lines will still disappear when they reach or get very close to maximum distance here i am struggling a bit because i didn't notice i forgot one comma on line 108 inside rgba color declaration just bear with me a bit nothing is changing about the code i'm just trying to find a problem now i notice the missing comma and suddenly everything works what i will do now i will copy these two lines and place them outside the if statement which thinking back was not necessary because lines are only drawn if we enter the if statement on line 107. now i just restore the formula to dynamically calculate opacity on line 105 and the base effect is done click the like please if you enjoyed this tutorial now it's time for a little challenge if you want you can change color of particles and lines around the mouse little hint on how to do that we already calculated distance between mouse and particles inside our update method so somehow preserve that value possibly as a new property on particle class constructor and here on line 106 you can create multiple if statements and say if distance from the mouse is more than a certain value change lines connecting the particles to a different color you can do the same thing with color of actual circles that make our particles inside update method on the particle class somewhere after the part where we calculate distance between mouse and particles also if you decide to get creative and take this effect to the next level by combining it with something like liquid or displacement svg filter we learned about in previous videos or some other cool effect let me know in the comments what you did and share the code if you want i have a playlist with many original creative coding projects like this one everything in vanilla javascript some quite advanced some more beginner friendly you can check it out if you want hope you had fun coding with me today see you next time
Info
Channel: Franks laboratory
Views: 28,426
Rating: undefined out of 5
Keywords: Vanilla JavaScript Text Animation Tutorial, vanilla javascript, javascript text animation, text animation, particles, physics, javascript particles, javascript physics, particles.js, particles js, particle.js, particle js, javascript tutorial, advanced javascript, tutorial, javascript, html canvas, html 5 canvas, canvas animation, web development, web design
Id: XGioNBHrFU4
Channel Id: undefined
Length: 59min 28sec (3568 seconds)
Published: Fri Aug 07 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.