Creative Coding: Particle Images & Logos | Frank Dvorak | Skillshare
Search

Playback Speed


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Creative Coding: Particle Images & Logos

teacher avatar Frank Dvorak, Creative Coding

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Watch this class and thousands more

Get unlimited access to every class
Taught by industry leaders & working professionals
Topics include illustration, design, photography, and more

Lessons in This Class

    • 1.

      Project 1: Slice & Dice Effects on Images

      1:00

    • 2.

      HTML, CSS & JavaScript setup

      2:41

    • 3.

      How to organise anything into a grid

      6:31

    • 4.

      How to draw, crop & slice images with code

      3:44

    • 5.

      How to animate images with code

      1:55

    • 6.

      Mouse interactivity

      1:59

    • 7.

      How to find the distance between 2 points

      3:07

    • 8.

      Getting direction from point A to point B

      4:58

    • 9.

      Motion physics formula (friction & easing)

      5:56

    • 10.

      Moving the cells around

      2:37

    • 11.

      Performance optimizations

      2:00

    • 12.

      Creative coding experiments

      4:31

    • 13.

      Project 2: Particle Images

      0:46

    • 14.

      Project 2 setup

      2:37

    • 15.

      Converting images to code

      4:25

    • 16.

      How to use canvas

      2:59

    • 17.

      JavaScript classes and particle systems

      3:21

    • 18.

      Drawing rectangles

      1:25

    • 19.

      Drawing images

      1:24

    • 20.

      Drawing particle objects

      2:26

    • 21.

      Effect class

      4:35

    • 22.

      Code cleanup

      1:07

    • 23.

      Multiple randomized particles

      4:14

    • 24.

      drawImage method

      0:42

    • 25.

      How to center images on canvas

      2:03

    • 26.

      Particle motion

      5:20

    • 27.

      Pixel analysis with getImageData

      6:09

    • 28.

      Extracting coordinates and colors from pixel data

      10:04

    • 29.

      Turning images into particle systems

      4:52

    • 30.

      Animated particle transitions

      2:57

    • 31.

      Animation on button click

      3:57

    • 32.

      Mouse interactions and particle physics

      11:30

    • 33.

      Creating unique animated transitions

      5:56

    • 34.

      Particle assemble effect

      9:09

    • 35.

      Particle print effect

      1:53

  • --
  • Beginner level
  • Intermediate level
  • Advanced level
  • All levels

Community Generated

The level is determined by a majority opinion of students who have reviewed this class. The teacher's recommendation is shown until at least 5 student responses are collected.

40

Students

--

Project

About This Class

Let's turn images into interactive animated pixels with physics (friction, easing) and let's make those pixels react to mouse. Discover the secrets of creative coding, from simple shapes to advanced algorithmic art in a single class.

The HTML canvas element is used to draw graphics on a web page. We can use it to draw lines, rectangles, circles, images, curves. Today we will go deep on rectangles and images, let me show you how far we can take it. Let's dive deep into creative coding and explore the possibilities of modern front end web development.

Learn the fundamentals of HTML canvas and discover how to develop, draw, and animate visuals and images with vanilla JavaScript. No frameworks and no libraries. I will explain all principles and techniques as we write our code line by line.

We will start by drawing a simple rectangle and image on canvas. We will learn how to turn these basic rectangles into a particle system and we will teach these particles how to take shape and colours of any image.

Have fun!

Meet Your Teacher

Teacher Profile Image

Frank Dvorak

Creative Coding

Teacher

Hello, I'm Frank. I'm a front-end web developer, owner of Frank's Laboratory YouTube channel. Come explore creative coding, game development and generative art with me.

See full profile

Level: Intermediate

Class Ratings

Expectations Met?
    Exceeded!
  • 0%
  • Yes
  • 0%
  • Somewhat
  • 0%
  • Not really
  • 0%

Why Join Skillshare?

Take award-winning Skillshare Original Classes

Each class has short lessons, hands-on projects

Your membership supports Skillshare teachers

Learn From Anywhere

Take classes on the go with the Skillshare app. Stream or download to watch on the plane, the subway, or wherever you learn best.

Transcripts

1. Project 1: Slice & Dice Effects on Images: I want to introduce you to a special motion physics formula. And once you know how it works, you will be ready to make the most epic interactive effects. The full understanding of what the code is doing is very important if you want to have a complete control and you want to be able to experiment and come up with your own new and unique effects. That's why, as always, we are using no frameworks and no libraries, Only plain vanilla Javascript and object oriented programming. Let's learn some beginner friendly slice and dice animations on images and cover three very important and fundamental techniques that will get you ready for the ultimate set of image manipulation effects. As always, this class is beginner friendly, but a basic understanding of HTML, CSS, and Javascript is needed to be able to follow and actually understand. 2. HTML, CSS & JavaScript setup: I create three files in my project folder, index HTML, style CSS and script S. Inside index HTML, I create a standard simple web page. I give it some title. I link my style sheet, I create HTML five canvas element with an ID of canvas one. And I link my script file. I will give it defer attribute to make sure all the contents of the page are loaded before the script runs intysSs, I give my canvas element a border. I center it in the middle of the web page, both vertically and horizontally. Using the absolute position technique. Like this in script GS, we do the standard HTML canvas, set up four lines of code that are always the same. First, we point Java script towards the canvas element using its ID. Then we take that canvas reference and we call a special get context method. And we instantiate a built into the canvas API like this. Now we can use this CTX variable to call all canvas drawing methods to access its properties. For this project, I set canvas width to 500 pixels and height will be 700 pixels. I make sure I set the size here in Java script and not in style CSS to make sure both element size and drawing surface size of my canvas element are set to these values. To prevent any distortions, we will be slicing images into a grid. Each cell in that grid will be a separate object. Here I have a blueprint for that cell object. We will also create a class. I call for example, effect the main brain of the code base. We will manage the state of the entire effect. From here, constructor will expect canvas as an argument inside I convert it into a class property. Yes, I can pull canvas variable from line one directly into my class. But I prefer to do it this way to keep my classes more self contained from that canvas reference. We will extract with and height because I want the dimensions of the effect to match the size of canvas. I create an instance of the class using the new keyword. It expects canvas as an argument, I pass it canvas variable from line one. If I consol effect, we can see it has three properties, canvas with and height. Everything works well so far. 3. How to organise anything into a grid: We want to slice the available canvas area into a grid. The width of each cell will be the width of canvas divided by, let's say, 35. We want 35 cells per row. The height of each cell will be canvas height divided by 55. We want 55 rows, 35 columns, 55 rows. Let's use the cell class from line six to first create just one cell object. All the code inside the class constructor is executed line by line when we create an instance of that class using the new keyword. If I do this, an instance of cell class will be created automatically. At the point when I create an instance of the effect class, I will consol Ok cell so that we can see its properties pop up in the console as we create them. It's a good way to check if everything is working as we build the project up, each cell in the grid will need access to properties on the main effect class. One way to do it is to create a reference pointing to the effect to the space in memory. The main effect object sits cells will be organized in a grid to cover the entire canvas area. Each cell will expect x and Y coordinates so that it knows where exactly in the grid it should sit. I passed this keyword referencing this entire effect class. At first, I want to draw this cell at coordinate 00. Top left corner of canvas, we can see the cell object correctly receiving the properties here in the console. I want all the cells to have the same width and height, so all of them will have access to cell width and cell height from the main effect object. Now we have enough information about each cell to be able to actually draw it on cannabas custom draw method. We'll expect context as an argument. Again, I could directly pull CTX from line two, but I prefer to make my classes more independent on their lexical scope. I will do it this way. Each cell will be just a black rectangle. For now, I can draw it from here if I want, but it wouldn't be practical. Since the image can be made out of thousands of cells. We will draw all of them from a custom render method like this. Now I call this render method from my effect variable. I pass it CTX from line two. We want to draw multiple cells and I want to organize them in a grid. The first cell will be here horizontally. The second cell will be here. We will be jumping by cell width horizontally until we cover the entire row. Then we will jump by cell height vertically to the next row. We will repeat this until we cover the entire canvas area. I will hold all cells in an array. I will call it image grid. To achieve this effect, you need to understand two fundamental creative coding and two, the animation techniques. Both are extremely important and can be used for thousands of different things just for the effect we are building today. The first technique we need to understand is how to organize anything into a grid. We will do it here inside a custom create grid method. To create a grid, we will use two nested four loops. Nested means there is a loop inside of another loop. The outer loop will handle rows in the grid. We will cover canvas from top to bottom, row by row. We will start from top from vertical coordinate zero. We will be running this four loop until we reach the height of canvas, which means until we reach the bottom, instead of jumping by one, we will always jump by cell height to make sure each row has the correct height. Every time we jump to a new row, we will use another four loop to cycle over all horizontal cells on that row, from left to right, from zero to canvas width. Let's write this all out and we will quickly recap how the logic works. Organizing objects in a grid is extremely useful technique to understand for creative coding and also for making two D games. For example, every time we jump to a new cell in the grid, we take image grid array and we push new cell in there, Passing it the reference to the effect object. This time we pass it X index from the inner loop and Y index from the outer loop to place the cell in the grid as we are creating it row by row, from top to bottom. To recap, the outer loop handles rows, the inner loop handles columns, the cells that sit horizontally next to each other. Inside each row, let's say we are on row zero, Y is a zero, We are up top. Here we enter the inner loop and we push one horizontal cell next to each other, jumping by cell width until we reach the width of canvas. We exit the inner loop. The outer loop will increase y by cell height. We jump to a new row again, we enter the inner loop, we place all the cells on that row from left to right. When we reach the width, we exit the inner loop, increase Y by one, we enter another row. And we repeat this process until we have x and y coordinates for each cell in the grid that covers the entire canvas. It's a very useful technique if you are a beginner and this is the first time you see this. Don't worry, it will make more sense if you use this more often. As we said, all of the code in the constructor is automatically executed when we create an instance of that class using the new keyword. For that reason, I can automatically trigger methods. From here, I will call create grid so that when we create an instance of effect class, a grid of cell objects is automatically created as well get an error because we don't have this cell here. Instead of this line, I will call for each method on image grid on the array from line 26. For each cell object we just pushed into that array, I will call its draw method. I want to draw all of the cells we just created in console. I can see that my array contains 1,980 cell objects. I will stroke them instead so we can better see the grid we just created. Nice work. I can change these values to increase or decrease the size of my cells. 4. How to draw, crop & slice images with code: Now I take an image. Ideally the image should be the same size as canavas. In my case, that's 500 times 700 pixels. I put the image inside my project folder and I reference it here. I give it an idea of project image. I don't want to draw the actual IMG element. I give it display none. We want to draw that image on canvas. Instead, I bring it into my project here on the main effect class. This image property inside render, I call built in draw image method. And I pass it the image I want to draw and X and Y coordinates. Where to draw it, I can move the image around like this. I can also give it optional width and height arguments. And the image will be stretched or squeezed to fit into that predefined area. I want to slice the image into pieces. So I will instead use the longest version of draw image method with nine arguments. This version gives us the most control over the image we are drawing or animating. We pass it the image we want to draw, source x, source Y, source width, and source height, the area we want to crop out from the source image and destination X, destination Y, destination width, and destination height to define where to draw that cropped out piece of image. On destination Cannavas, let's say I want to crop out this area between coordinate 00.200 400. And I want to stretch that cropedout piece over the entire canvas. We are stretching it from coordinate 00 to canvas. With canvas height, we have full control now These four values determine the cropping area. These four values determine where to draw that cropped out piece of image. On Destination Canavas, I want each cell to contain a small piece of image. I will cut this line. Instead, I will put this image property on the cell. Now we are drawing the image many times, once for each cell in the grid. We can't afford to do this because canvas is actually very efficient at drawing images. It doesn't have to calculate anything. It just takes the image data and it draws it. It's a cheap operation compared to drawing a shape. If I draw the same image at x and y coordinates of each cell, we get this. If I give it with height, each cell contains the entire image. We already know that we need four more arguments to crop out a piece of that image. Source X, source Y, source width, and source height. We already organized these cells in a grade. We already have the values of the crop in coordinates. We can just do this simple. Now, it looks like we are just drawing a single image again. But actually at this point, we are drawing a piece of the image from each cell. And the cells combined together create the full image. How can I prove this? For example, I will use autogenerated index. Here two arguments we need brackets. Only draw the cell with index of 300 or 500. Only draw the cells with an index higher than 500 or lower than 500. Lower than 600, 801,000 201,300, I think we have proven the point. This is no longer a single image, it's made out of many pieces. 5. How to animate images with code: For the next step, I will create an animation loop. We will be updating some values and redrawing the cells over and over again to create an illusion of movement. I put render inside I call built in request animation frame. And I call animate to kick the animation off. It looks static, but we are already animating. I can prove this. I give each cell slide X and slide Y properties. Very different things will happen depending on where inside the draw method we add these. I will add these to source X and source Y coordinates that determine the cropping area. But we could also add them to destination X and destination Y for a completely different set of effects. If each cell has the same slight value, the entire image will move. But what will happen if we randomize them? This randomizes them just once on the first page load. What if I create an update method and I randomize this for each animation frame? For each animation frame we call update and we will redraw all the cells over and over again. Interesting. I hope this doesn't give someone a headache. I can also randomize slide Y like this beautiful chaos, Creative coding. I can also make the image slide to the side. Higher value, I guess. Yes, move faster. Move in the opposite direction, right? I think we've proven that we are indeed animating. We can also make the grid visible here. 6. Mouse interactivity: I can delete this consolo. I want to capture mouse coordinates. I create an object here that will hold them for me. Radius will be the interaction area around the mouse in which the cells react to mouse presence in some way. I take this canvas reference from line 28 and I add mouse move event listener. I can declare event listeners here inside the constructor. We already know this means they will be automatically applied when we create an instance of effect class. The only thing here is that the callback function cannot be a regular function. It needs to be an ES six arrow function to allow us to use this keyword that points to this effect object and its properties from inside this call back. Otherwise it would be undefined. Arrow functions inherit this reference, this keyword from the parent scope. I can consolog the autogenerated event object. If I open it, we want the x and y coordinates of the mouse cursor. Important thing here is that these values are only good for us if the canvas is full screen. Since my canvas is not full screen, I need X and Y coordinates that account for the white area around canvas. I will have to use offset X and offset Y values. Instead, these properties account for the white space between the webpage and canvas to give us the correct mouse position in relation to canvas. Since I used an arrow function here, I can access domus x from inside the call back and I can set it to do offset x. I do the same for the vertical Y coordinate I tested by consologing these values. I move mouse over the canvas and I'm getting the coordinates. 7. How to find the distance between 2 points: Now the second most important technique we'll use today. We want to calculate the distance between two points in a two D space, in this case, between mouse and the cell. To do that, I will need D X the distance between the mouse and this cell object on the horizontal x axis. I will have a helper property here. I call x velocity on the horizontal x axis. If I do slide x plus equals dx, we get complete chaos. Let's finish this. I also need D Y, the distance between these two points on the vertical y axis. To calculate the distance between these two points in a two D space, I need to calculate a hypotenus. We have this side and this side. The distance between these two points is the hypotenus, the longest side of the right triangle. Which means I can use Pitagora's theorem formula, which would look like this in Java Script. But since we are in Java Script environment, we can also use built in masted hypotenus method, which will give us the same value, the distance between mouse and this cell. I say if the distance is less than the radius value we defined on the mouse object. We will do some emotion physics. We will create a helper variable. I call for example, force. It will be equal to the ratio between the current distance and the radius, which represents the maximum possible distance within which the cells will react to the mouse. I said velocity x to force for each animation frame, we increase slide horizontal cropping area for each cell by this V X horizontal velocity. As I move the mouse around, it's clear we are actually detecting the distance already. I say L. If the distance is more, make sure the cells stop sliding. Vertical velocity will also be equal to force. We add it here. I define it up here. I will stop the sliding in the L statement again. Okay, we are getting there on the first page load, we are getting some movement in the top left corner coming from the coordinate 00. That is because I'm setting mouse x and y to null at first, but in this case, Javascript sees these as 00. Even though it's better to manually set the null, in this case I have to set to undefined instead. Now there is no movement at first in the top left corner that fixed it. Also, when the mouse leaves canvas, the last known mouse position will continue to interact. I copy this code block, turn it into mouse leave event. Here we will also set them to undefined. Now we get animation. Only when we move mouse over canavas. We are making great progress. 8. Getting direction from point A to point B: Now I want the image slices to expand in the correct direction, directly way, or towards the mouse. This is quite advanced. If you never used math 82 before, I had to use this method for a few projects before I understood it better. Don't worry if it's not entirely clear after using it once. If you are an animation beginner, you can just rewatch this part. Or you can watch many other tutorials I made where I use this technique. This technique is something a creative coder uses a lot. And it will be clear once you start using it and you play with the values to see what they do. Built in math 8102 method will give us an angle in radians. We can use this angle value to get an angle between two points in a two D space and make two objects move towards or away from each other. In this case, the two objects are the mouse cursor and the cell containing the slice of the image. We are already calculating DX and DY, horizontal and vertical distance between the mouse and the cell. Method 82 expects these arguments to give us the directional angle between them. It expects y first and D x second. It's important to remember, it's just how this built in method works. Method 82 gives us an angle between two points, mouse and cell. In this case, it returns the angle in radians between the positive x axis. And a ray from 00 towards a certain point. The way we use this, the ray goes from object one from the cell towards X and Y of the mouse. Keep in mind that mouse can be to the right or to the left of the cell, which means we can get positive or negative values. The value range is between plus pi and minus pi Using mouse first or second here in this formula will result in a different set of values. The resulting angle values will be organized differently, but in creative coding we don't really mind because once we get the animation, if the objects move towards each other, we can swap their direction by multiplying the values by minus one. What I'm saying is we can adjust the code later to whatever values method e two is given us. I will show you to recap. For our purposes, method e two takes DY and dx, the distance between two points on vertical, horizontal axis. Based on these two values, it will give us an angle between minus pi and plus pi. From that angle, we know in which direction we want to push the objects to make them move towards or away from each other. The range of values between minus pi and plus pi covers the entire circular area. Because full circle is two pi, 360 degrees, this means we are covering all the possible directions on a two D plane. I know this is a lot of math for beginners, don't feel the pressure to fully understand all of this at this point. Practice will make it clear once you understand this technique, you can make so many really cool effects. It's worth the effort. Okay, now we will pass this resulting angle value to sine and cosine methods, which will map their position along a circular area. Sine and cosine can work together if they both get the same angle input to create a circular motion or wave emotion, depending on how we use them. Since sine and cosine convert these angle values between a range of minus one to plus one, we would barely see any motion at all With these small values, we are multiplying that small directional vector by force increasing its radius. We know that force is directly related to the ratio between the current distance between the two objects, mouse and cell, and their maximum possible distance. This will add a lot of nice physics into our project, and the motion will look smooth and natural. We are at the point where I check what motion we get. Then I will just adjust the values to get the motion I want. I synchronize sine and cosine output by swapping them around, we get this motion instead. This is how you can get circular motion radiating away from the center point. In this case, our center point is the mouse cursor. I have this L statement here to make the image slide back into place when the mouse moves away. But to get a completely smooth motion where the image pieces slide back and forth. Ideally, the entire thing should be calculated as a single value. And then we apply that final value to slide x and slide y properties. This will give us much better result, but how do we do it? 9. Motion physics formula (friction & easing): I want to have a calculation here that is a result of two competing forces. The first part here is the push away from the mouse if the mouse and the cell are close enough to each other. The second portion of this calculation will be a force that slides the images back to their original place. Since both of these forces will be a part of a single formula, we will avoid getting any motion back and forth because only a single value will be calculated here in the end. Let's expand this formula and explain it. The first part is the force displacing the pieces. And the second part will be trying to put them back to where they originally were to their initial positions. Now they slide back too fast. Keep in mind this entire update method runs 60 times per second, over and over. Recalculating these values for each animation frame. I don't want to push the slide all the way back, but only by a fraction of the difference between the current position and the original default position. I multiplied by easing to create these individual steps in between like this. I want them to slowly ease back to where they were. I try different values and I see what happens now. At the same time, I want the push force to decay over time, getting gradually weaker. In the real world of physics, we call this force friction. For each animation frame, I want the force to have only 80% of the push power. Meaning that it will gradually get weaker and weaker and it will eventually get overpowered the second half of the formula that is working against it, trying to slide the cell back to its original place by a fraction of the difference between its current position and its initial original position. I do the same for the vertical y coordinate. We slide the cropping area of each cell by applying two competing forces on it. These forces work against each other, but they are both a part of a single formula. We get a smooth motion. As a result, if the distance between cell and the mouse is less than radius value we predefined, we are calculated vertical and horizontal force pushing the slides away from the mouse. That push force is applied to slide x and slide Y values as the first part of the formula. And that push force decays for each animation frame by friction, the speed of that decay can be modified by giving this friction a different value. Then we are applying a force in the opposite direction. If there is a plus here, we need a minus here. And that opposite force is a fraction of the difference between the particles original and the current position. As the push force slowly decays and the animation runs, eventually this right side of the formula take over and slides will ease back into their original place. I encourage you to play with all these values. Swap, sine and cosine, swap plus and minus, give friction and ease different values. You can also apply this formula to x and y of the cells instead, to get a completely different effect. After you run your own experiments and randomly come up with cool and unique effects, these calculations will make even more sense. I can comment out the rectangles we are drawing because this will make the effect more performant. Drawing images on canvas is cheap, but drawing shapes is expensive. Even rectangles that are one of the simplest shapes, the value we give to ease will define how fast the pieces slide back into place. The value we give to friction will define how fast the push force decays per animation frame. Friction always needs to be less than one and more than zero. If you give it more than one, then the push force will just compound endlessly and the image will never reassemble itself again. Not only these values themselves, but also the ratio between these two values will affect the motion. Now the push force decays only by 1,000 per animation frame, which means it stays high for a long time. Dot is basically slicing the distance between the base original position and the current position into multiple pieces and move it back towards that original position one slice at a time. If this dots is 0.01 we move towards the original position by 100 of the distance between the original and the current position per animation frame. But as the push force the case by 10% per animation frame, it will eventually allow the cells to slide back into place. I'm not sure if my explanations at the end helped or made it more confusing. The best way is to play with the values yourself, see what motion you get, and it will start making sense. Now that we covered this technique, you are ready for more advanced version of this effect, where we turn each pixel in the image into a particle and we apply similar physics formula to them. We can also increase the number of cells that make up the image. The more cells, the more performance demanding the effect will be. Of course, right now, I'm asking Javascript to draw 3,500 images 60 times per second, and slide their cropping areas around calculating motion physics for each cell. It still runs pretty smooth on my computer, but I probably shouldn't use so many cells. It just shows how good canvas is at rendering images. 10. Moving the cells around: Okay, this was the beginner friendly version of the class. I'm coming back to give you some quick fire experiments. I delete this consologe, we have these four variables to move the cropping area inside each cell, and to slide it around. I will create four more variables. And these four will move the cell position X and position Y for horizontal and vertical position of each cell. And speed X and speed Y for their movement. Speed, slide X and slide Y are applied here to source X and source Y. Arguments passed to draw image method, they determine the position of the crop in area. We are sliding that crop in area using VX and VY. Now I take position X and position Y a separate set of variables and I apply them to destination X and destination Y arguments. This area will be for the crop effects, this area will be for cell positions and movement. They will work nicely together. If we do this, well, let's see how it goes. Speed X will be the final target position minus the starting position. We will do easing again. We will slice that journey into ten pieces. And we will move cell towards its target position by one tenth of the distance per animation frame. Speed Y is also the target position minus the starting position divided by some ease in value. Now I can take these values and apply them to position X and position Y, since we are using those here inside draw image as destination X and destination Y. This will actually move the cells themselves like this. They all move at the same time, so it just scales like this. We can make this much more interesting in many different ways. Let me show you some of them. For example, each cell will have a randomized value 2-12 And we will ease each cell by its own randomized ease in value 2.52 we can change the starting positions here. The cells will fly out of different points, different corners of canvas, for example, Depending on what we do here. Bottom right corner, bottom middle. Nice, I told you, we will make this more interesting. Notice that the images still react to mouse by sliding the cropping area. 11. Performance optimizations: I can also stroke them, but I have to use position X and position Y here. Yes, this is so cool. Stroking these rectangles affects performance. Let's reduce the number of cells here. This still looks great, don't you think? Let's try to find a good cell size. The only problem is that this code block runs all the time. I want to save some performance and stop calculating these small pix values. The cells are close enough to their original target positions at the point when the image has been assembled or at least almost assembled close enough. I say only if speed x is more than 0.1 or speed Y is more than 0.1 Only then move them around. Otherwise, we assume they already assembled the image. These calculations are not needed. Now, we don't have any speed x and speed Y. We need to set them when the cell is created. Let's give each cell a custom start method. Here we will set the speeds. We will automatically call this start method from the constructor. Problem is that cells can be to the left or to the right. Speeds can be negative or positive. Basically, I want to run this code only when the speeds are less than -0.1 and more than plus 0.1 Which means the cells are far enough from their target positions and I want them to move. Let's just remove the minus. By wrapping these in method absolute, like this, it will return the absolute number. Okay, this code block is moving each cell from its starting position towards its target position. Once the cells are close enough and the image has been assembled, we don't run this code block anymore to safe performance. 12. Creative coding experiments: I want to test if this code block actually stops executing. We were passing cells index value from the for each loop. Here I want each cell to have a unique index value that increases by one for each new cell we create. I pass that value to cell class constructor. As the fourth argument, I make sure it's expected here and it's converted to a class property. I will consolo the index of each cell here. I want to make sure all of them stop running this calculation at some point when the cells are close enough to their target positions and the image has been assembled, the limit of how close we want them to be can be changed here and here. Yes, we can see all the indexes stop being locked at some point. Consolo like this will slow your project down. We need to make sure we remove it when we don't need it. We can do so many other things. Each cell has a unique index value. We call start method automatically when we create each cell. We could also delay them by putting set time out. Here we pass it callback function. How long to wait before this runs? I don't want to delay all of them by 500 milliseconds. Each one will be delayed by its own index value. Callback will run the start method and this will give us an error. The reason is this keyword, it becomes undefined in the scope of this call back. We already faced this issue with callbacks and this keyword here, inside event listeners. We know there is a simple solution because arrow functions inherit this from the parent scope. We turn the call back into an arrow function, and here we go, we have a custom delay. We can increase that delay by multiplying index here cells cropping area still slides around. While all these things are happening, nice, now I can change the starting positions here to get a set of different interesting effects. How about the middle? Instead of pushing the cells into the array, I will unshift them, fill in the cells array from the other end, and this will result in the cells coming from the back of the image like this. If you are experiencing performance issues, I recommend removing the stroke rectangle coal from line 32 or you can draw less cells. By adjusting cell with cell height properties on the effect glass, we can make them come from the top middle. Like this. We can also randomize their starting X and get a different effect. How about random X and bottom Y? We can also clear old paint between every animation frame to get an effect like this. How about random X and random Y0x and random Y negative X, and random Y0x and zero y? They all move at a consistent ease. Then I can get more organized patterns by adjusting these two values. I gave you so many more values you can tweak. Now it's time for you to take what we learned and come up with your own unique combination. We have a complete control and we understand how this code works. If you are unclear on some of these, play with the values and watch what happens. It will start making more sense. Eventually, we can take this to a whole new level. By making each cell just a small pixel in the image, we can have images that are made out of many more pieces. Turn images into particle effects and even particle rain or particle fire, for example. If you are ready to take your images to the next level, I'll see you in the next part. 13. Project 2: Particle Images: Javascript is a powerful tool. Let's explore the secrets of drawing and animation techniques in modern front end web development. In this class, we will start by drawing a simple rectangle and image on HTML canavas. We will discover how to turn these rectangles into a particle system. It will be a smart particle system that can recreate and remember shapes based on pixel data. From any image, I will show you how to give each particle physics such as friction and easing, and we will add some mouse interactions where we can break the image into individual pixels and it will automatically put itself back together. Come join me and let's learn how to turn images into interactive digital artworks. 14. Project 2 setup: We start by creating three files, index HTML, style CSS and script GS. I open index HTML. In my internet browser, I will be using Google Chrome. Inside index HTML, I create a basic web page markup. I'm using visual studio code editor with met extension, so I can just press exclamation mark and tab key and I get a basic web page boilerplate like this. This video is a HTML canvas introduction. But I expect that you know, some basics of Java script. Give my web page some title. For example, awesome Javascript Effects. I link my stasis as file like this. I create HTML five canvas element with an idea of canvas one. Html canvas element is used to draw graphics on a web page. We can draw static shapes, as well as dynamic interactive animations that react to user input, which is what we will do today. The canvas element is a container for our artworks, it's our art board. We can use Javascript to draw shapes, lines, text, or images on it. It might sound very basic, but once you understand how canvas works, you can do an infinite variety of digital art, interactive games, and web graphics. This course, we will explore what can be done with images and we will go from basics to some really cool advanced effects. Hop I create a diff element with a class of controls, and inside we will have a button with an idea of Warp button and text that says Warp. When we click it, it will break image into individual particles and the image will reassemble itself again. Automatically, we will be able to control the speed and the weight of particles as they move. This project will also contain some two D physics. Don't worry, it's not that complicated if you take it step by step with me as we write the code. We will also link script G file down here at the bottom. To link our Java script logic in stysSss, I start with global reset to make sure our page appears the same across all different browsers. I use asterisk selector to target all elements on the page, and I set margin to zero. And padding to zero canvass with an ID of canvass, one will have a blue background. This is just temporary so that I can see where it is on the page when I'm positioning it with a class of controls will be set to position absolute. This will remove it from the document flow and place it over the canvass element. We need to make sure that the buttons it will contain are not covered by anything and are always clickable. So I set its z index to 100, putting it all the way up top in front of all the other elements. 15. Converting images to code: I go back to index HTML and I create an image element. I give it an ID of image with the source of the image. We will have to do a little trick. I have my image files ready on my desktop. It's just a normal image in PNG format with a transparent background. If I just put this image into my project folder and I point image source attribute to it like we would normally, we will be able to draw that image on canvas, but we won't be able to analyze it for pixel data and break it into particles. If we try to do that, we will get an error that says canvas was tainted by cross origin data. This error should only happen when you run your code locally. Once you upload the project to an on line server, the PNG file in the source would be considered the same origin. But we want this project to work at all times. We don't want to trigger any errors even when we work locally like this. To bypass tainted canvas warning, we will convert the image itself into code. We assign that code as a source here. And that way the image itself will be part of index HTML file. Therefore, it will be considered same origin in all circumstances, most people don't know that images on the web can be broken into a single very long line of code. We call this a base 64 string. That line of code contains all the image data. Completely replacing the PNG file we have here. I can convert my image into base 64 format by drawing the image on canvas and then calling built in two data URL method on canvas element, turning the entire canvas with that image drawn on it into a data screen. Today, we will use even simpler option to do that and we will use one of many available websites that will do it quickly for us. I open another browser window and I Google phrase PNG two base 64. I select the first link from online Png tools.com If you want to use the same images I'm using, you can download them in the video description images are enemies from Steampunk Fish game tutorial I made recently. I can simply take the image and drag and drop it here on the right hand side. It generates base 64 code for me. For the code to work, I need to make sure the string starts with the data colon image, PNG base 64, like this. If it doesn't start like that for you, just make sure you take this checkbox. We took a PNG image file and we converted the entire image into a line of code. This string now contains all pixel positions and color values, completely replacing the image file itself. Any internet browser can understand this string and draw the image from it. You want to learn how to use the other method and generate this string dynamically with Javascript without using an external website. I do that in my other course, where we generate complex fractal shapes and make them into falling snowflakes. I highlight this very long base 64 string and I copy it in index HTML. I place my mouse courser between the quotes on SRC attribute and I paste all of that inside. If I save the changes we are drawing the image, you can see base 64 string contains the entire image. No need for the actual PNG file. This way we can manipulate it with Javascript in any way we want. You can click View Word Wrap to toggle between a view where it breaks lines like this, we can see all the code. And another view where the whole thing is on one line like this, you can see there is a lot of code. Years ago, I released a simple version of this algorithm. And it would only work with small images, 100 times 100 pixels. Anything bigger than that would become very slow and laggy. This version works even with larger images because we will control how many particles the image breaks into with Java script. This code base has many improvements and optimizations. You will see the bigger image you use, the longer base 64 string you will get. Instead of pointing image source directly to a PNG file, we converted our Angular Fish image into a base 64 string. This will allow us to analyze the image for pixel data and do all kinds of cool effects and animations on it without having to deal with any cross origin errors. I don't really want to draw the image element on my web page. I want to draw that image on my blue canvas element. I will take IMG tag and I give it a display, none, the image is hidden. But we can still access it with Java Script to draw it on canvas when we need it. It's still sitting here in index HGML. 16. How to use canvas: In script GS, I create an event listener for load event. All the code in this project will be written inside this event listener. Load event will make sure that the entire website, including all dependent resources such as style sheets and images, is fully loaded and available before we run any Javascript code. When working with Javascript code that depends on an image, it's a common error that happened to me many times that I didn't wait for the image to be loaded and I was getting blank canvas. Javascript code gets executed very fast. Images can take a couple more milliseconds to load. We can't perceive that difference by naked eye, but if Javascript code runs before the image is loaded, we will get blank canvas load Event listener is one of the ways we can deal with this delay. We start with a simple canvas set up. I create a constant variable. I call for example canvas. And I pointed towards the HTML canvas element we created in index HTML file. By using get element by ID, we gave it an ID of canvas one. Like this variable I call CTX. Shortcut for context is this canvas variable from line two get context. Context is a special method that can only be called on a variable that holds a reference to HTML. Five canvas element get context method expects an argument, we call context type, we can pass it two D or web GL. Today we will work with two D when called like this get context method will create an instance of an object called canvas Rendering Context two D. This object contains all canvas settings and all built in canvas drawing methods we will need today. I can consoloc CTX to have a look at it. I can see it right here. If we open it, we can see all the default canvas settings, so called canvas state. You can see, for example, that the default fill style is set to block here, default font is ten pixels, san serif, that default line width is one pixel. We can override any of these settings by assigning them to a different value with Java script, and we will do that later. If I click on the prototype here and expand it, we can see all the built in two D methods. We can use these methods to draw rectangles, circles, and lines. We can create gradients and manipulate images. Today, we will cover the basic ones and we will go really deep on draw image method that sits right here. I will also show you how to analyze an image pixel by pixel and use that for some cool animation magic with get image data method which is coming from here. Let's delete the consoloc and close the browser console. I take canvas variable from line two and access its width property. I set it to window in width to make canvas cover the entire browser window horizontally. I also do the same thing with height to make it cover the screen vertically. 17. JavaScript classes and particle systems: Today I want to show you how to create a so called particle system. Generally speaking, particle system is a collection of small objects. Each particle is a small graphical element. It can be an image or a shape. We can program these particles to look and behave in a certain way to simulate all different kinds of effects. It could be fire, bouncing balls, swarms of enemies in a game, or many other things. Today, we will make each particle into a pixel in our image and we will break them into individual pieces. At the same time, these particles will react to mouse in a nice dynamic way with physics and friction involved. To create all these particles, we will use a custom Javascript class. I call it for example, particle like this with a capital P. Javascript classes are blueprints to create many similar objects. Javascript is a prototype based language. Every Javascript object has an internal property called prototype that can be used to extend object properties and methods. Classes in Javascript are so called syntactical sugar. It's a cleaner and more elegant syntax built over native Javascript prototype based inheritance that mimics classes from other programming languages. Simply said, class is a template. Every time we call this particle class, it will create one new particle object for us. We will also have a class I will call Effect. This class will handle the entire effect, all the particles at once. The last piece we'll need here is Animation Loop Particle class as a blueprint to create individual particle objects, effect class to handle all particles at the same time. And animation loop To make it all animated and interactive, I will give my particle class constructor method. This is a special method when I call my particle class later with the new keyword constructor will run all the code inside of it to create one new blank object and assign it values and properties based on the blueprint inside. Let's define that blueprint. Let's define the properties of our particles. Every particle will be a piece of an image, a pixel. It will need to sit at a very specific position and all the particles combined will make up the whole image. That means it will need x and y coordinates so that Java script knows where on canvas to draw it on HTML Canvas, same as in web development in general. We have horizontal x axis going from zero pixels on the left and increasing as we move right. We also have a vertical Y axis starting at zero pixels up top and increasing as we go down. For example, position 5,100 on canvas will be here 50 pixels from the left on the x axis and 100 pixels from the top on the y axis. Initially, I will set x and y two coordinates, 00 for top left corner on canvas. When we define properties on Java class, we say this x, which means x property. On this instance of particle class the constructor is creating, right now our particles will be rectangles because Canvas is faster at drawing rectangles rather than circles. In the previous version of this effect, I used circles. This time we will be able to draw more particles efficiently. Size of each particle rectangle will be three times three pixels. 18. Drawing rectangles: To draw a rectangle on canvas, all we have to do is take CTX variable from line three that holds an instance of canvas two D join API and we call built in phil rectangle method like this. It expects four arguments x and y position where to draw it and with height of the rectangle it will fill that rectangle with color. If we don't define fill style, we know that default style on canvas element is black. Here is our black rectangle drawn 120 pixels from the left on the x axis and 150 pixels from the top on the y axis, 100 pixels wide and 200 pixels tall. If this is your first canvas project, you should maybe post the video and change these values so you understand how rectangles, same as images on canvas, are drawn from the coordinates we give it. And they go to the right and down from that point, depending on their width and height. We can also draw circles, curves or lines and make different shapes and animations. With these, you can draw pretty much anything. Once you know how canvas works, if you are interested in art that can be done with lines, check out my class on fractals. Today we are going deep on images. Let's bring our angle fish image into the project and draw it on canvas. 19. Drawing images: I create a constant variable, I call image one. I pointed towards the image element using its ID image one, which I gave it here. Now I can take CTX variable from line two which as we said holds all canvas properties and methods I call built in draw image method like this, draw image method expects at least three arguments. The image we want to draw and x and y coordinates. Where to draw it? I pass it image one from line seven and I want to draw the image from the top left corner of canvas from coordinates 00. I give it position of x 100. We push the image on 100 pixels to the right. If I pass it on 100 pixels as vertical y coordinate, I push the image on 100 pixels down. I can also pass it optional with and height arguments. If we don't pass with and height, Javascript will just draw the image at its original size. If I pass it width of 100 pixels and height of 100 pixels, we squeeze the image into an area of 100 times 100 pixels and we distort it. I can stretch and squeeze the image like this, which could be useful for certain effects. If this is your first time using draw image method, you can post the video and pass it different values for x Y with and height so that you can see how it affects the position and size of the image. 20. Drawing particle objects: Now we know how to set up a Htimlcnvas project. We know how to use fill rectangle method to draw a simple rectangle and how to use a draw image method to draw an image on canvas. Let's use our particle class to draw something. I delete this code. Let's say I want each particle to be black square of 30 times 30 pixels. I give my particle class a custom method. I call, for example, draw. Its job will be to take properties from class constructor and draw particle of that size at those coordinates. Let's start simple and then we refactor it to employ good practices of object oriented programming. Again, to draw something, I take CTX variable from line three. From it, I call built in Phil Rectangle method. We already learned that Phil Rectangle expects four arguments x, y, width, and height. That Java script knows where to draw that rectangle and what size it should be. I pass it this x from line 11. This dot y from line 12 as x and y coordinates. I pass it didot size from line 13. As with the same disdote size property as height like this. We define our particle class. We have a blueprint with all the properties. And we have a draw method where we take those properties and use them to draw a rectangle. How do we actually run this code? To draw it, we need to create an instance of this class. I create a constant variable, I call particle one. I set it equal to new particle like this. The new keyword is a special command in Java script. It will look for a class with that name. It will find that class here on line nine and it will automatically trigger its constructor. Method constructor will create one new blank object and it will assign it properties based on the blueprint inside. Because this particle one object was created using this particle class, it has access to draw method we defined on line 15. We can simply call it like this, particle one draw. Nice. We are using our class to create and draw one particle. I can adjust its X and Y position here to move it around. I can also change its size. 21. Effect class: If I want to create more than one particle, I can just repeat this code and create variables for particle two, particle three, and so on, but that would not be very efficient. Our code should be dry, which is an acronym for don't repeat yourself. We are also trying to keep everything in object oriented code structure. We can use this effect class we defined on line 20 to create and handle multiple particles. Particles will handle individual particles. Effect class will handle the entire effect, all the particles at once. I give it a constructor this time. The constructor will expect two arguments for width and height to come from the outside. This will make sure that the effect is aware of the current canvas dimensions Inside I convert these arguments into class properties. I'm saying take the width that was passed as the first argument to the class constructor and convert it to width property. On this particular instance of effect class you are creating right now, same for height. We will also have particles array property. Initially, I set it to an empty array, it will contain all currently active particle objects created by particle class. From line nine, I will give my effect class a custom method I call, for example in it, its job will be to initialize the effect and fill particles array from line 24 with many particle objects. Let's start with just one particle. I take this particles array and I call built in push method on it. The push method adds one or more elements to the end of the array. I want to push one particle in, so I pass it new particle like this. The new keyword will jump to line nine and it will trigger particle class constructor creating one new particle object based on this blueprint. I delete this code. We will draw shapes from inside our effect class. Now to draw this one particle we are holding inside particles array I create draw method. This method will take particles array from line 24 and it will call for each built in array method on it. The for each method executes a provided function once for each array element. I will use modern ES six in tax here. This is so called arrow function. Now particles array contains only one particle, but it can also contain many. I'm saying take that particles array and call for each on it. Assign each object in the array a temporary variable name particle on each of those call their associated draw method. From line 15 we have effect class with init method to fill particles array with particle objects and the draw method to draw all of them. This draw method on line 29 draws all the particles, the entire effect. This other draw method on line 15 specifies what will each particle look like. In our case, we decided to draw them as simple black rectangles. For now to draw the particles, now I create a constant variable. I call effect, and I set it to an instance of my effect class like this. On line 21, I can see that constructor expects arguments for width and height. I pass it canvas width from line four and canvas height from line five. Let's consolo this effect variable to check if everything works so far. Nice. I can see my effect object and it has width and height properties and also particles array that is currently empty. I take my effect variable and I call it method from line 26 like this. This method should push one particle in there. I check in console, yes, we have one particle object inside and I can see it has x, y, and size properties that all have correct values. If you see undefined in some of these, it means there's a mistake somewhere in your code. It's good to check from time to time as you write your code, if all your properties have values, especially if you run into some problems or errors while coding consoloc is here to help us. Now I can take effect variable again and I call draw method from line 29. I also delete the consoloc. Nice, we are drawing one particle using our new code structure. I can move the particle around by changing these values. 22. Code cleanup: We are doing something bad. Here we are pulling CTX variable from line three directly into our class. We want our classes and objects to be modular, self contained as much as possible and independent from their surrounding code, from their lexical environment. Rather than pulling CTX directly, I will convert it into a variable and pass it along. I will make sure draw method on particle class expects context as an argument. I will then use that context variable here to call phil rectangle method from it. I will pass tx variable from line three as an argument to draw method. When we call it on the effect class on line 36 we give it a variable name context here like this. We pass that reference along to draw method on particle class. That reference will be passed here. From there we call Phil Rectangle. Doing it like this will make sure our code is modular. It's considered a good practice rather than what we had before. 23. Multiple randomized particles: We can also randomize particle positions. Rather than hard coding the coordinates, I can set horizontal x position to a random number between zero and canvas weight. Vertical Y position could be a value between zero and canvas height. Now every time I refresh my page, particle will be at a different random position somewhere on canvas. I could also randomize the size if I want to. Inside it method, I create two particles by copying this line. Nice, Now we have two particles as we create them using the new keyword. Every time the constructor runs on line ten, it will assign different random x and y position to each one. I can also create three particles like this, same as we did with CTX variable. Here we are pulling canvas width and canvas height directly into our class, which makes this class dependent on its surrounding code. We are already converting canvas width and canvas height two class properties on effect class here by passing it to effect class constructor on line 36. Let's remove these two particles to make sure each particle is aware of the current canvas size. I make sure particle class constructor expects a reference to the entire effect class, entire thing as an argument inside I convert that reference to a class property called this dot effect. Keep in mind that objects in Java script are so called reference data types. Which means that by passing a reference to the entire effect object to this particle object, I'm not creating a copy of effect class each time I create a new particle. This dot effect is not a copy, it's just a reference pointing to a space in memory where the main effect class is stored. It has many advantages. The main one is that when we update any values on effect class, those changes will be immediately visible from this dot effect property on particle objects. Now this dot effect points towards this entire effect class, and we can access any properties on it from inside particle class. Because of that, I can replace canvas width by dist effect dot width, referencing the value from line 23. As we know, this value represents canvas width. We can also do that here on line 13 and use dist effect dot height, a value coming from line 24. If you are a beginner passing values around like this might take some time to fully understand. Don't worry about too much. If you are struggling, you will become good at this as you write more object oriented code basis. Now that we know that particle class expects an argument pointing towards the main effect class. Here on line 28, where I create an instance of particle class, I pass it effect as an argument, a reference to all of this, this entire class. However, since we are inside that effect class, I need to use this keyword instead. This keyword used inside this class represents the entire class itself. When I refresh the page, I have one particle being randomly generated and drawn somewhere on canvas. Nice. We are passing canvas width to the effect class on line 35, converting it to this thought width property on line 23, and using that value on line 12 to calculate particle position. We are also doing the same for height. Now I can copy this line again to create many particles. But what if I want 100 particles? Copying this line of code would become impractical. This is a perfect scenario to use a four loop. I delete all this code, and instead I will wrap this in a four loop. Like this. Index will start at zero, as long as index is less than ten, increase index by one and create one particle. This four loop will run ten times and create ten particles. Four loops are great to help us reduce code repetition. 24. drawImage method: Let's also draw an image. But because I don't want to be pulling this image one variable into my classes from the outside. Let me just turn it into a class property on the effect class like this. I'll call it Did image. We can draw it by taking context and calling draw image on it. I pass it dot image from line 24.00 for x and y coordinates. We are drawing our fish on canvas again. But this time we are doing it from a self contained object oriented code base. 25. How to center images on canvas: Images on canvas are drawn from top left corner, going right and down. Let me show you how to center an image exactly in the middle of canavas. I will create a helper variable called this center x. It will be this dot width from line 21. So the width of canavas times 0.5 middle of canvas horizontally, dot center Y is dot height from line 22 times 0.5 the middle of canvas vertically. I can use these new properties as x and y coordinates passed to draw image method. Now the image is drawn from the point on canvas that is exactly in the middle. However, the image is not centered. Dot image is a reference to IMG element we created in index HTML. Let me consologate This image element has automatically generated width and height properties. If I consolog dot image width, you can see it. It says 500 pixels dot image dot height is 369 pixels. Now that we know this, we can delete the consoloc. And we can use width and height of the image to offset position by half of image width and half of image height. To center it, I create a property called dot x on effect class. In this case, distotex means horizontal position of the fish image. It will be dot center x from line 25, so the middle of canvas area horizontally minus half of image width. Now I can pass didot x to draw image method on line 37. And the image is centered horizontally. Let's do the same for vertical Y position dot center Y minus Sdt image dot height times 0.5 I replace it here. To center any image on canvas, just find the middle of canvas vertically and horizontally, and offset those values by half of image width and half of image height. 26. Particle motion: So we are drawing our fish as an image and we are drawing ten particles. Let's make it 100 particles. Let's make each particle a square, five times five pixels. You can play with the size. Whenever I refresh my page, all these hundred particles get a random position somewhere on canvas. We can also make particle size random, like this. We can also make these particles move. We will handle that logic here. Inside update method, I will need a new property called V x velocity x, which is basically a horizontal speed. Let's set it to 11 pixel per animation frame. For now, I also create velocity y and I set it to plus one as well. Inside update method for each animation frame, we want to increase horizontal position from line ten by the value of Vx from line 13. We also want to increase position Y by the value of V Y. Each particle will have its own update method that will define its movement. I also create update method on effect class. This method's job will be to call update on all currently active particle objects inside. I take particles array. For each particle object in the array, I call its update method, which is created on line 19 like this. If I call update method like this, not much will happen. All particles are just drawn once and their properties get updated once. There is nothing Calling the update and draw methods over and over, we need animation loop. I take these two lines of code and I put them inside this custom function I called animate. I call request animation frame built in method. It sits on the window object, but it can be called directly. Like this request animation frame method will call a function we pass to it as an argument before the next browser repaint. When I pass it animated the name of its parent function. It will constantly draw all particles and update them over and over, creating the animation with request animation frame. The number of call backs is usually 60 frames per second. It will generally try to match the display refresh rate in most modern browsers. It will also automatically pause the animation when running in background tabs to improve performance and battery life of the computer. When I call animate and run my code, we get this. Our black rectangles are moving and leaving trails. The trails are the old animation frames. If we want to see only the current animation frame, we have to delete canvas every time we update particle positions. I do that by using built in clear rectangle method. I want to clear canvas from Corin at 00. I want to clear the entire canvas. I take values from up here. The width of the cleared area will be canvas width. Height will be canvas height. Now we are animating. Congratulations, you are a creative coder. You just built a working particle system. Particles are moving because we are adding velocity x and velocity y to their current x and y coordinates. If we want each particle to move at a different speed, I can assign them a random speed from a predefined range when they are first created here inside particle class constructor, I can, for example, set their speeds to be a random number 0-10 That's very fast. If you want the particles to move in all possible directions, not just right and down, we can push the speed range to start from negative numbers. This line means a random number between minus one and plus one. Particles with minus value will move left. Particles with a plus value here will move to the right for vertical y coordinate. It's the same. Particles with a minus value here will move up. Particles with a plus value will move down since each particle will be assigned a different random velocity x and velocity y at the point when they are first created by the constructor. Here the ratio between V, x and y will give each particle a different direction and speed of movement. Each particle will have a different vector. Let's remove the blue background and leave canvas background transparent. How do I make my particles take the shape and color of the image and how do we make them remember that shape and recreate it? If we break it with mouse, we are about to learn that right now. This concludes the first part of the course where we covered the basics of HTML canvas. We learned how to make a simple basic particle system and how to handle, draw, and center images on canvas. The second part of this course will be more advanced and we will learn more about image manipulation and particle physics in depth. Congratulations, If you are a beginner and you follow the far, you are doing great. If the code in the following lessons feels more challenging, don't worry. In this next part, we are entering advanced creative coding territory. But I think you can do it. We will take it step by step, and I will do my best to help you understand. Let's go. 27. Pixel analysis with getImageData: This is our custom particle class. Its job is to create one new particle object every time we call it. With the new keyword. Right now, our particles look like small black squares. I actually want to pixelate the image and make each pixel block a particle of a specific color. That particle also needs to remember where it sits in the overall image because we want to be able to push them around and do other tricks with them, and we always want them to find the way back to their original position to recreate the image. Here on line 36, we have initialized method just simply pushes 100 random particles into particles array. I comment this out, we need to find another way to turn our image into particles. Also keep in mind that distote x from line 33 and distote y from line 34 define horizontal and vertical position of the fish image we are drawing on canvas. I can prove that by increasing diste x by one for each animation frame here. Which will make the fish move to the right on the positive direction. On horizontal x axis. I delete the code from init method and I put draw image inside. The job of this initialized method is to draw image on Canvas, analyze it, and turn it into particles. Then we delete that image from Canvas completely, because we will have our particles making up and recreating the image itself. Let's do it step by step. Since we are drawing something from inside in it, we need to make sure it expects a drawing context as an argument. I call it on line 48 down here. And I need to make sure I pass it that context CTX variable from line three. It gets called only once on the first page load Here, Animate will immediately clear the canvas and delete the image for a moment. I will comment out animate to stop it from running, let's focus on initialized method. Here is our custom particle class that creates our particle with these properties. Then it draws them as black squares and makes them move, updating their positions. We will use this particle class and we will make it turn each pixel in the image into one particle. Inside it method I create a temporary helper variable called pixels. This will be an array containing all the positions and color values about each individual pixel on Cannavas. We can't analyze image itself. We need to draw the image on canvas as we are doing here on line 37. And then we use get image data to analyze our canvas element with the image drawn on it. Get image data method analyzes a specific portion of canvas and returns its pixel data in the form of a special image data object. It needs four arguments to specify which part of canavas we want to analyze. I want to analyze the entire canvas element from coordinate 00 to the width of canavasdizotwidth from line 27 and the height of canvas height from line 28. The important thing to mention here is that get image data some built in security measures when we run the code locally, as we are doing in this project right now. If we draw an image file and then try to analyze that canvas with that image drawn on it, we will get a console error that says canvas was tainted by cross origin data. Even if you put the image file in the same local folder as your script file, it will still be considered cross origin. That's why we did the whole thing in the beginning, where I converted image file into a base 64 string. Doing that, the image itself becomes a part of index HML file. We can avoid this tainted canvas warning. Let's consolok pixels to see image data object in console. I can see that get image data correctly returned image data object. Inside this data property, it contains a massive array representing color values of each pixel in the entire canvas element. This is a special type of array, so called UI NT eight clamped array. It's an array of unassigned eight bit integers clamped to arrange 0-255 If you worked with web colors before, you know that every color can be expressed by RGB and alpha value called RGBA color declaration. We use it in CSS all the time. In this case, red, green, and blue can be any value 0-255 In CSS, alpha opacity is a value 0-1 here in this array, alpha is also a range 0-255 where zero is transparent and 255 is fully visible. This array is organized in a special way, where each four elements represent red, green, blue, and alpha of one pixel. Four elements in this array are one pixel. This is important to remember. I just opened the beginning of the array and canvas gets analyzed by kit image data from the top left corner. That means that this top left corner pixel has zero red, zero green, zero blue, and zero opacity. It's a black transparent pixel. Second pixel is also zero red, zero green, zero blue, and zero opacity. Zero opacity means these pixels are completely transparent. The only visible pixels on canvas are the ones making up our fish drawing. If you search through the array, especially in the middle, you will start seeing values 0-255 here, where each value represents red, green, blue, and alpha of each individual pixel. I get all zeros here because a big portion of the canvas is transparent. There is nothing here until we start drawing the fish down here. The pixels themselves are of course much smaller. I'm just using this pick red square as a visual help. Imagine the red square being one times one pixels in size. 28. Extracting coordinates and colors from pixel data: I delete the console. We drew image on Canavas and we analyzed its pixel data. Now we have color of each pixel on Canavas store. In this pixels variable, I want pixels variable to point to the array directly, not to the entire image data object. I say data pointing towards this unsigned eight bit clamped array. Now I will cycle through that array row by row, from top to bottom. If alpha value is more than zero, it means those are the pixels that make up the fish, the non transparent ones. When I find a non transparent pixel, I will create a particle object for it using our particle class. Each time we find a non transparent pixel, we will create particle that represents it. To cycle through something row by row from top to bottom, we can use so called nested four loops. Nested simply means it's a loop inside of another loop. The outer four loop will handle vertical y coordinate. It will jump row by row from top to bottom until we reach canvas height and then we stop. I don't actually want each row to be only one pixel high. I want to jump by bigger increments which will pixelate our image and it will make the effect more manageable. We can't really create 40,000 particles and still get smooth animation. It is possible to do that, but that would require advanced optimizations that I won't be covering in this class. We want to decrease resolution a little bit. Instead of jumping by one pixel when we finish a row, we will jump by a certain value. I call for example a gap. It's not really a gap, but more like size of individual particle pixel that will make up our image. We will be able to dynamically change it. It doesn't really matter what value I give it. Now just remember that higher value in Gap means better performance, but more pixelated image, I said gap to, for example, five pixels. Every time we finish going through one pixel row, we jump by five pixels down and we start analyzing those pixels. Every time we enter a new row, we will go from left to right until we reach the width of canvas area. Each time we jump from position to position, we jump by the gap value. These nested four loops might be a bit challenging to wrap your head around at first. The outer loop is a vertical y position jumping from row to row. The inner loop maps horizontal x positions going from left to right for each row. Let's say we start here, y is zero. We enter the inner loop and we go from x05 pixels at a time, step by step, until we reach the width, the end horizontally. We exit the inner loop. We enter the outer loop, and y increases by five, and we are on another row. We enter the inner loop. Again, we go from left to right, five pixels at a time. When we reach the end, again, we will exit the inner loop, enter the outer loop, y increases by five. We enter the inner loop and we go over horizontal x positions. These loops will keep going until we reach the bottom of canvas, canvas height here. At that point, we cycled through all the pixels in the image. This technique is useful for many other creative coding effects. When you need to cycle through a grid, it's a good thing to know and it becomes much easier when you use it. More often, we are going through the entire canvas, row by row, five pixel jumps. Each time we jump to the next cell in this imaginary grid, we want to check if there are any colors there or if we are currently going over the transparent area. If we find some colors, we create one particle using our particle class. We want to make that particle remember its x and y position, its position in the image and its color. The challenge is that as we cycle through this massive pixel data array returned by get image data and stored in pixels variable, the indexes of the array go from zero to tens of thousands. We need to find a way to take that linear series of numbers and get x and y coordinates from it, and color as well. Let's start by getting the index, the current index of the pixel we are currently going over in our grid in that massive pixel data array. This formula is a bit advanced, so don't worry if you don't get it at first. The current index of the pixel is y from the outer loop, the number of row as we go through the image row by row from top to bottom times the width of canvas we are analyzing. That will give us, for example, a block like this. Then we add the leftover horizontal pixels, depending how far along we are in the new row plus X. For example, something like this. We are five horizontal pixels into the new row. All of that needs to be in brackets and multiplied by four because we know that in the unsigned eight bit clamped array returned by get image data, each pixel is represented by four positions in that array. Four values for red, green, blue, and alpha. We want that actual array index as we jump from pixel to pixel. This line is here to make sure we know where in the pixel array at which index we currently are. As we cycle through the pixels in the image, row by row, we are mapping a linear line of numbers to X and Y coordinate. If you still don't fully understand it, feel free to rewatch this last part, or don't worry about it too much. Being able to understand logic like this is for math experts, we are creative coders and Javascript developers. You don't really need to understand advanced formulas like that, especially if you are a beginner. You just need to know when and how to use them. We know that each pixel is represented by four integers in the array. We know that red pixel value is the first one pixel array from line 39 current index in that array we are currently on like this. We know that green value for that same pixel is next index plus one. Then there is an integer representing blue value index plus two and we have alpha opacity index plus three. After that, we have again, red, green, blue, and alpha for the next pixel. Now that I have red, green, blue, and alpha of that pixel, I can concatenate it into a good old standard RGB color declaration. I can say RGB opening bracket in quotes like this, plus red from line 43 plus plus green plus coma plus blue plus a closing bracket. The thing is, we don't really care about transparent pixels this entire area. We are not creating particles for the transparent pixels in this area. We care only about the pixels that make up our angle fish image. The pixels around are white because the body of the website behind it is white. The canvas itself is transparent in these areas. It's alpha, there is zero. I can say if alpha from line 46 is more than zero, meaning that pixel in that area is not transparent. Only then create a particle for that position. We create a particle by taking particles array from line 29 and calling built in array push method. We push one new particle object created by our custom particle class from line seven inside the array. Our particle class right now only knows how to randomly spread black square particles around canvas. We need to teach it how to expect this new pixel data and correctly arrange itself to form an image. If you feel that I'm going a bit too fast right now, let me know. I will recap this pixel analysis technique step by step. Once we have the entire logic in place, we are almost there. Inside initialized method, we just cycled through the image row by row, capturing X and Y positions and RGB value of each particle. I need to make sure that particle class constructor expects these values like this inside I convert them into class properties. Rather than setting this X to the X value passed as an argument, I will create a new property called origin X. This property will always remember where that particle sits in the overall image. I set it to X that was passed as an argument. This X was calculated in our nested for loops. After we analyzed canvas for pixel data origin Y will be y. That was passed as an argument. I will wrap these values in mathoed floor to round them down just to make sure we don't get any sub pixel values. And canvas doesn't have to use antialiasing to smooth the image out. It's good to mathod floor everything we draw on canvas for performance reasons. This color will be color passed as an argument from here. It will be coming from that RGB color we concatenated a while ago on line 50 so that each particle retains the original color of the image. Okay, now particle class constructor on line eight expects effect x, y, and color as arguments. I go down inside our main effect class again, whenever I create one new particle, I pass it this keyword to represent this entire effect object. As the first argument, I pass it index from the inner four loop as horizontal position, y from the outer four loop as vertical y position and color. That's how you analyze image for pixel data and convert it into a particle system. If this was a bit too complicated for beginners, if you are still following, well done, now it's time to have some fun with Animation. 29. Turning images into particle systems: Just to recap, initialized method will run just once on the first page load. First we draw our image on canvas, then we use get image data to analyze the entire canvas element. For pixel data, that pixel data comes in a special array where every four elements represent one pixel. It's red, green, blue, and alpha values. We put it into nested four loops like this. To convert a linear series of numbers, indexes in the array into x and y coordinates. We use width and height of the image to know where each row and each column breaks to map them correctly. As we jump from cell to cell in our imaginary grid of five times five pixels over the entire canvas, we extract red, green, blue, and alpha values if alpha is more than zero, if the pixel is not transparent, we create a particle at that position using our custom particle class. Now let's draw and animate this in it. Method will run just once on the first page load. Let's consoloc effect to see if we have all pixel particles there. I can see my effect object here created by our custom effect class. From line 28 inside I see particles array we defined on line 32. It contains 2,775 particle objects. This number will depend on the image you are using, how much of the image is transparent, and also on the resolution at which you scanned the image. In our case, we scanned it at resolution five times five pixels defined in this gap property. On line 38, I can see that each particle has color reference to the main effect object, origin X and origin Y positions, horizontal and vertical speed, and the current X and Y positions. If you see undefined in any of these in your project, it means there's a typo somewhere in your code. We have to make sure all these properties have values for the effect to work. Uncommen animate on line 76, which will immediately delete the fish image and create a set of black particles. I want those particles to start moving to their origin x and origin y positions to recreate the image. Before we do that, let's just set this dot x to x. That was passed as an argument. This dot y toy like this. Yes, the fish shape is there perfect. Each particle also remembers the color of the image. We just need to use it. Let's set Phil style to this dot color like this. Nice. The fish is breaking into pieces because of VX and VY properties. I set V x zero and VY to zero perfect. Now you know how to recreate an image as a particle system. I have this dot gap property on line 39, which determines how much detail we want in the image. The lower the number, the more performance demanding this effect will be. Gap is five pixels and I'm drawing particle blocks of ten times ten pixels. There is a lot of overlap. I can set it to five, or when I do four there will be one pixel. Gaps in the grade can make it dynamic by saying this effect Do gap. That way the size of particles will change automatically as we change this dot gap property. Large value means lower resolution. Don't use any decimal points here. We don't want sub pixel values for performance reasons. Also, drawing particles as rectangles is more performance efficient. I made a tutorial for all the version of this effect before, where each particle was a circle. This new version with rectangles will be much faster when we start animating it and make it interact with mouse. Drawing rectangles is faster than drawing circles on canvas. And when you have 3,000 shapes, 3,000 particles or more, you can really feel the difference. We can make the gap even two or three pixels, which will result in a sharp image. I don't recommend doing one pixel. That will give you way too many particles depending on the image size, and it will run slow when we animate it. There are some canvas optimization techniques and algorithms we can use to make even one pixel particles move smoothly. But I won't be covering that in this course. I can make particle size always one pixel smaller than the current gap value to get some space in. You can play with the values to see what happens. So far it looks like we just pixelated the image. But keep in mind that each pixel block is a particle object, can give it physics and behavior. For some really cool effects, I said gap 23 pixels. For now, I will consoloc particles array from line 33 by saying effect particles array like this. Because I said gap to three pixels we get 7,557 particles that make up the fish image. 30. Animated particle transitions: I want the particles to always try to move to their original position. So that when we push them around with mouse or we break the image apart in some other way, particles are always being pulled towards their original positions. I want the image to always automatically recreate itself whenever it is broken. We will write that logic inside update method on particle class. Let's start simple. Without any physics, this position plus equals the difference between origin position, which is the particles position in the image, and its current horizontal position. Y plus equals z dot originy minus ty. We want particles to always be aware about the difference between their current position and their original position in the image. We are calling update method on effect class here inside animation loop on line 74. Inside that method, we are triggering update method from line 23 on every individual particle object. Here on line 63, let's put these values in brackets and let's spread the particles around canvas. At the initial page load, this x will be method random between zero and canvas width times dot effect. With to actually see the movement, I need to make sure that individual step per frame is just a small fraction of the difference between the current exposition and the original exposition. Like this. I do the same for dist y. I set the initial vertical position to a random value between zero and the dist effect dot height, which is the height of the available canvas area. Let's do very simple physics. I will call it, I set it to 0.2 and I use it here and here. By changing this value, we change how fast or how slow the image assembles itself. It might be interesting to randomize this value and have every particle move at a different speed. Maybe if you want slow motion, make sure that is a very small number. Well, this is pretty cool. We can have so much fun with this code base. Now, isn't it great what you can do with just one Elga script? We are not even using any libraries. We wrote all this logic ourselves. We can play with this effect in many ways. Even just changing the start in x and y position will give us something different. Like when I sat starting x to zero or I spread starting y across a much larger area. We can also do simple shrinking effect. This would look different if the speed or easing of each particle is random. There are many ways we can play with this code base. I can also spread x and make Y zero. I'm just having fun with it now. 31. Animation on button click: Let's create a button that we clicked. We'll randomize X and Y positions of each particle and we will get a nice animation of image reassembling itself every time the button is clicked. I will call that, for example, Warp, like a teleport from sci fi movie when people get broken into particles and reassembled. When this Warp method runs, horizontal x coordinate of each particle will be randomized between zero and effect width. Y will be a random value between zero and effect height. Like this, I will also give it a different value just to experiment with it. I go to the main effect class. And the same as we did with draw and update, I create a warp method. When triggered, it will cycle through particles array. For each particle object in the array, it will run warp method from line 28. Let's go to index HTML if you want that long base 64 data string that contains our image to be on one line. In visual studio code editor you can select view word Wrap from the top navigation panel. Here we have a diff with a class of controls and inside there is a button with an ID of Warp button back in script GS. I go down here and we will manage that Warp button functionality. I create a constant variable, I call Warp button and I set it equal to document get element by ID Warp button. Like this. Then I take it and I add event listener for a click event. In the callback function, I take an instance of effect we defined on line 35 and instantiated on line 76. And I call its associated public warp method from line 71. Like this, this main Warp method will call Warp on each individual particle, randomizing x and y positions and setting as to a different value. Now your users can trigger this school animation by clicking on the Warp button. Awesome, let's make the button a bit nicer. I'm sure you know how to style something with CSS, and this is not a CSS course, but let's do it anyway. I take all buttons on the page. Currently we have only one, And I set padding to 20 pixels, font size to 30 pixels, margin to ten pixels. Padding ten pixels and margin 20. Maybe I open another browser window and I will go to Google Fonts website. I will search for a font called Bangers for the school comic book art style. I click this plus button to add it to my library. Then I click View Selected Libraries, and it gives me these three link tags. I can just copy them and paste them up here in index HTML, I make sure I put them before my custom style CSS file to make sure it's available there. Then all I have to do is to copy this CSS rule for font family and I apply it to controls. No, okay. I have to apply it to the button tag itself. Let's delete this. Perfect 40 pixels, font size, text color white, background color black. Just to make it interesting, on hover, I swap the color. Text color, black, background white. Nice. Let's give a transition of 0.2 seconds. Okay, I like this. We turned image into particles and we added a warp pattern that will play a transition. It will show off how our image automatically reassembles itself when broken apart. Let's add more physics and interactivity by making individual particles react to the mouse. 32. Mouse interactions and particle physics: I want the main effect class to always be aware of the current position of the mouse cursor, I create a custom is mouse property. It will be an object with three properties radius. I will initially set to 3,000 It will define the area around the cursor where particles react to the mouse. It won't really be 3,000 pixels. I will explain why the number is so high when we get there, it's for performance reasons. X and y position of the mouse cursor will be undefined at first. Class constructor runs once at the point when the class is instantiated by calling the new keyword. We can take advantage of that and we can actually add any code in here that we want to be executed at the point when effect class is created. I can even add event listener in here like this. We will listen for mousemove event. I need to make sure that this event listener is bound to its current lexical scope. I want it to be inside effect class constructor so that I can override mousex and mousey properties as mousemove event fires. To make sure that the callback function on this event listener remembers where inside which object it was first defined, I can use a special Java script bind method or change the callback function into an ES six arrow function. Sometimes we also call it fat arrow function. One of the special features of arrow functions is that they automatically bind this keyword to the surrounding codes context. It will always be able to see this domouse property, which is exactly what we need here. We need access to the autogenerated event object, since this arrow function will have only one argument. I can even remove the brackets like this. Whenever mousemove event fires, I take this dot mouse dot x from line 47 and I set it to event x current horizontal coordinate of the mouse cursor. I will also set this dome doty from line 49 to event y. Like this. Let's test if it works by consologin mousex and mousey. Because I put that mousemove event listener inside class constructor of effect class. It will get automatically applied when we instantiate effect class here on line 86. Save my changes, refresh my browser window. Now when I move mouse over canvas, I can see mouse position is updated and updated values are being correctly saved in our custom dot mouse property on effect glass. Perfect. Let's delete the consolog on line 88. Also, this one on line 54. It's good to always delete consologs like this. For performance reasons, we are capturing the current x and y coordinates of mouse. Here we want each particle to keep checking how far it is from the mouse. If the mouse is close enough, we want the particle to be pushed away by it. We will write that logic inside update method on particle class x. Distance on the horizontal x axis between mouse and this particle is dot effect mousettx from line 50 here minus st x dy Distance between mouse and particle on vertical y axis is this dot effect dom y minus disty. To calculate a distance between two points, we can use Pitagorian theorem. It works like this. This is mouse, this is a particle. We create an imaginary right triangle between these two points. This is the x horizontal distance. We already calculated that on line 25. This site is a DY distance on the vertical y axis. We calculated that on line 26. To get this site, which is the actual distance between these two points, we use Ptagora's theorem to calculate hypotenus, the longest side of a triangle opposite to the right angle. Pitagora's theorem formula is C is equal to square root a squared plus b squared converted into Java script. We say to distance is mouth square root from disto dx times stod x which is a squared plus so times Didi squared. That gives us the distance between two points, between particle and mouse. I remove square root because this is a very performance expensive operation and we don't really need it. I just need to adjust mouse radius to a larger value if you are not using square root here. That's why I set mouse radius to 3,000 here on line 51. You can adjust the range when you see how large it is when the animation is going in a minute. I want to implement some physics. I want the particles to be pushed harder if they are closer to mouse. I do that by creating a help er property called to force. It will be a radius of the mouse, the area around the mouse where particles react to it, divided by the current distance between the mouse and the particle to make the particle moved away from the mouse in the right direction. I need to put minus here. We will see how it works when we have some animation. You can try to put plus and minus here and see what happens. The force at which the particles are being pushed is equal to the ratio between the radius of interactive mouse area and the current distance of that particle from the mouse courser. I check if distance is less than mouse radius. If it is, we push the particle away from the mouse. Before we do that, I'm using some new class properties that aren't defined in the constructor. Let's define them first. Dx, dy dot distance, and didot force. All these properties will be zero at first. I will also create another property I call for example, dot angle. Dot angle will determine the direction at which the particles are being pushed away when they interact with Mouse down here we will calculate that angle using matote a 102 built in Javascript method. Matote 8102 method returns a numeric value in radiance between minus pi and plus pi. We know that circle is two pi in radiance. This value that matoteen two returns is representing so called theta angle between a given x and y point and positive x axis like this. Important thing to remember is that this built in Javascript method expects a value of the y coordinate first and the x coordinate second. The difference between x Andy position of the particle and the x Andy position of the mouse cursor represented by Diddy and dis dot x past the method 102 method gives us an angle value. We will increase horizontal speed, Vx velocity x, by force from line 33. That depends on the ratio between mouse radius and the distance between mouse and particle making particles that are closer being pushed by a bigger force to specify which direction they are being pushed. I pass this angle. We are calculating on line 3062, most cosine method. This method will map that angle we pass to it in radians as a value between minus one and plus one. This value will represent the cosine of the angle and it will make the particles float along the outer edges of the circle nicely as the mouse interacts with them. These a tin two and cosine methods and everything to do with trigonometry is quite difficult to explain if you see it for the first time. I don't think it's important to fully understand it as long as you know how to use it and how to get the movement you want. When we get the animation going, I'll play these values to see what it does. The visual feedback we get when the animation is going might make it easier to understand. This is hard, so don't feel bad if you didn't follow all this trigonometrical logic. It doesn't affect your ability to be a good Javascript developer. Now we updated VX from line 16 by accounting for force of the push and direction of that push. We will do the same thing for vertical speed, but this time we will use method sine. We pass at the same angle. Method cosine and method sine work together to map a position along the radius of a circle. Now I can use VX and VY vertical and horizontal speed, x and y position calculated here like this. Let's try first to see what it does while particles certainly react to mouse. But something is wrong. I'll fix that in a second. To improve the physics, we can also apply friction. I create a property called friction. I set it to 0.95 I multiply V x by it here, making it slowly decrease in its strength. For every animation frame, the motion is wrong. But still, I think it's interesting to check what is happening. I can see I made a typo here on line 33. It's supposed to be D x times dx, dy times dy. Like this, Pitagra's theorem. Now, the particles behave as expected, perfect. We are pushing them around to make them return to the original position. We have to do times equals here. If I change as to 0.2 we get much faster motion. The lower the value of friction, the more friction will be applied. There is a lot of math here. Don't focus on that too much. This course is mainly about Java Script and drawing on Canvas. You can use these math code snippets for other projects. Even if you don't fully understand how the math works yet, I encourage you to play with the values change minus swap signing sign, try to break it and see how it affects the movement. I hope it will make it more clear to see what is happening at what happens when I increase friction and increase radius, we get this more gradual boundary. There is an extended version of this course linked in the description below, where we take this even further and create some special transitions. You can check it out if you want. I hope you found some value today. I'm here for you to help you learn Java script and discover all the amazing things you can do with it. Do you think this was a difficult project with all the algorithms? How difficult was it for you? Give me a number in the comments. One is extremely easy, ten is very difficult, five is something in between, I feel later. 33. Creating unique animated transitions: Let's swap the image to something else. You can use your own PNG file with a transparent background or you can download the same image I'm using in the Assets section. This image is another character from my other Javascript course where we explore an alien planet and it's strange mechanical life forms. We can convert image into base 64 String with Java Script. But it's quicker to use an external website if you want to see how I convert images drawn on Canvas to a data like this on the fly, dynamically part of Javascript code base. Check out my other creative coding course about lines, rotation, and fractals. In there, I explain step by step how to create my procedural fractal. In effect, same as we did before. I Google PNG to base 64. There are many sites that can do this. Just make sure that the converted code starts with the data colon image. If it doesn't take this checkbox, I copy the long line of code. I go to index HTML and I want to replace it here on line 15. It's easier if I enable word wrap In visual studio code, I click View Word Rap. I want to replace all this code in source attribute. This code is the entire image. In visual studio code, I can just highlight the portion in the beginning. Then I scroll down where the code ends and to highlight everything in between, I press and hold Shift key and I left click where I want the selection to end like this. I deleted and I paste in the new code we copied from the website. Here we go, we swap the image and everything works awesome. This effect is really fun to play with. I find it very relaxing. For some reason, I adjust friction on line 19, I said mouse radius to 3,000 For example, back in index HTML, I go to view word wrap to toggle it off, it's better to have the long base 64 data string on a single line, otherwise we have to scroll down a lot. I copy this markup for work button and I give it an idea of block button with text that says blocks in script GS. I copy this code block and I adjust it to point towards that new block button. In visual studio code you can multi select like this by highlighting a text each time you hold down command on Mac and control on PC and you press letter D, you will select another occurrence of that text. I save a reference to block pattern, I attach event listener to it and inside I call effect block public method. We need to create it. I make sure I'm inside effect class down here where we created Warp. I create blocks method. Its job will simply be to cycle through particles array from line 56 For every particle object in that array, it will trigger method that is also called Blocks. We need to make sure that each individual particle has a method with that name. I go up here to particle class and here where we created Warp Method. Before I create this new blocks method, inside I can do all different kinds of things to mess the particles up because we know they will assemble back into an image shape. Again, because of the logic inside update method we wrote before, I can, for example, split particles into two groups. One group will be coming from the top of canvas, coordinate zero. The other half of particles will be coming from the bottom of canvas from vertical coordinate equal to canvas height. I can do it by using so called ternary operator. It's the only Java Script operator with three operas. This case we will use it as a simple one line if L statement. The structure is simple condition to evaluate, question mark, something to do if the check evaluates the true colon. Something else to do if it evaluates the false. The condition to evaluate will be to check if method random is more than 0.5 Method random called on its own, like this, will return a random value 0-1 It should be higher than 0.5 in roughly 50% of cases for those particles set their vertical position to zero. The top for the other half of particles, set their vertical Y position to affect height. The bottom of canvas ternary operator condition to check if true, do this, else do this. Now when I click Blocks pattern, it splits the particles into two groups, coming from top and bottom. Nice, I can change the value in actually in Warp will be 0.2 in blocks. We can try different as that way when we click different buttons, particles have different easing different speed, we can change any properties of the particles we want. Here I can, for example, make them larger. Let's set size of individual particle rectangle to ten pixels. Interesting. The problem is when I click Warp, now the size of particles stays at ten pixels. I have to remember when I manipulate a new value in blocks method, I have to define it for Warp method as well, if I don't want the size to be the same Like this. Now Warp has small particles, blocks gives us large pixel blocks coming from top and bottom. 34. Particle assemble effect: This next effect is really cool. In index HTML, I create a new button with an ID of assemble button. And text says assemble in script GS. Down here again, I create a section where I create a variable to store a Java Script reference to that new button, and I give it an event listener inside. We call effect assemble. Inside Effect class, I will create a top level version of assemble method that will manage all particles, same as we did with Warp and Blocks up here inside particle class, I need to define this new assembly method and give it some logic. Inside we set x to a random number between zero and effect width. Y will be a random number between zero and effect height. I want the particles just to be randomly spread around the available canvas area. I need to define ease and size. Since we are changing these values on under buttons as well, it does the same thing as warp. I want it to behave differently when it's reassembling the image. I want the particles to go back to their original position in the image, but not all at once, but one by one. At a specific speed, we will have to create a switch that will enable and disable each particle's target seeking behavior. Right now, the particles always want to return to their home position in the image. I need to have a switch that will prevent them from doing that. And create a traffic light system that says stop and go. I will write that logic that will delay particles from getting back to their original position. And then I will recap the entire logic loop. Don't worry too much if you don't fully understand everything in the first round. Let's write it first. Down here on the main effect class, I create a property called this counter. Initially, I set it to zero. This countervariable will be slowly increasing. As it increases, it will allow more and more particles to move back to their original position in the image. Each particle will wait a certain number of milliseconds before it starts moving back to assemble the image. That delay in milliseconds will be equal to this countervariable inside the master assemble method, I set counter to zero. This is important because we will have another transition that uses the same counter. We need to make sure that counter is always zero when assemble button is clicked or as we click between different transition buttons. We will have here, it will make more sense in a minute. Each time assemble method is triggered on each individual particle, they will be cumulatively increasing that same single counter variable by calling assemble on each particle object inside particles array, each particle will push counter value higher by one. I will create a set timeout here. Java Script set timeout method calls a function after a certain number of melliseconds set timeout sits on the window object. Same as request animation frame. We can call it directly like this. It expects two arguments function to call and delay how long to wait until we call it as a delay, I will use this dot effect to counter the value that increases by one every time each particles assemble method is called. That way, each particle will slightly delay the next one coming after it. As for each method inside the main effect class calls assemble method on each particle object one by one. The function to call after that increase in delay will be an arrow function because we are inside a class, inside an object. And I need to make sure that this keyword is bound to the context where the set timeout is defined. As we said before, ES six arrow function binds skewed to its current scope automatically. That way I can use this dot inside here and it will work. Alternatively, we would have to use the Java Script bind method here. Using arrow function is simpler syntax and it does the same thing as I said, I want to create a traffic light system where particles are told to stop and go. We will do that by creating one more helper property called this dot active. When particle has active set to true, it can move. If active is false, particle will freeze at its current position. After set timeout, timer goes off. We set active to true up here in particle class constructor, we initially set active also to true. Inside update method, we have code that reacts the mouse code that returns particle to its original position to assemble the image. I want all this code to run only if active flag is set to true. Down here when assemble button is pressed, we randomize x and y positions of each particle, spreading them all around canvas. We set easing speed and size. At that point, as the particles are spread out, we set this active to falls, freezing them all in place. As the for each method runs inside the main effect class, it cycles very quickly through the entire particles array, from the starting index to the ending index. Each time this code runs for new particle, the counter slightly increases, increasing this delay value. Each particle in the array will have slightly higher counter value, causing this set timeout to be called with an increase in delay. When set timeout finally triggers, each particle will be set to active true. And the if statement we created inside update method on line 32 will finally allow it to move back to its original position. While at the same time it will also allow mouse interactions. That was fun because the value of timer is equal to the delay in milliseconds that each particle has to wait before it becomes active. Increase in timer by a larger value here will actually make the assembling slower particles have to wait more milliseconds before they can move. The speed of the assembling itself will also depend on the image and what resolution you have in this gap property. Because if your image is made out of less particles that are bigger in size, it will assemble faster. You can also slow it down by multiplying the counter value by something. That way you are also increasing the milliseconds. Therefore, you are slowing down the assembling process, Multiplying it by anything less than one will speed it up. I think this is really cool how particles wait in place until it's there, turned and then they jump into position to recreate the image. We can also play with mouse interactions as the image is assembling and it will still work, they will just fall back in place when we allow them to. This is a pretty solid code base, I think. Feel free to do your own experiments with it. One problem we have here is that when we click Assemble button, it will instantly set that timeout sequence for all the particles. And if we swap out and back into this assemble transition, if the timeout hasn't activated yet, the animation will be starting from somewhere in the middle. We also need to clear all timeouts, all particles. Every time we activate assemble effect that the image always starts assembling from the beginning. One way to clear timeouts is to capture them in a variable. I create a new variable called this dot timeout. Initially, I set it to undefined down here on line 68, where we create a new timeout. We set it equal to this dot timeout. It will actually activate as it did before. Setting it equal to a variable like this will have no effect on how the timeout triggers itself. It, however, gives us an easy way to clear it when assemble is called. First, I want to clear the timeout if there is an active one clear timeout method in Java, cancels a timeout that was previously established. By calling set timeout, it expects one argument which will be an identifier of the timeout we want to cancel. Set timeout returns an ID when called, but we have it in a variable, so I can just pass it this time out like this. And it will work in here. I'm actually not sure why it's still going from the middle. It has something to do with this number being too small because when I do this, it will reset correctly. It works with larger numbers. When I go into too many decimal points, it assembles from the middle. I think it is, because the number we are passing as milliseconds delay is too small for the beginning indexes in the array like this, it works really well. Maybe it's better to adjust assembly speed by controlling by how much the counter increases here on line 68 experiments. 35. Particle print effect: Let's create one more transition effect. I call it particle print because it reminds me of three D printer. Creating something layer by layer, row by row. I create another button with an ID of particle print button and text that says particle print. As usual, we bring the button into the project. Down here in this area of script, we give it an event listener for click event and we will call particle print method. We create particle print method down here, same as assemble. It will also need counter to be reset back to zero. Then it will cycle over the entire particles array from start to finish. It will trigger particle print method, which we will define. Now I define it up here and it will work very similarly to assemble method. This time I want the initial x coordinate to be exactly in the middle of canvas area. This effect with times 0.5 Now all the particles come from this single line in the middle. If I said the initial y coordinate to the middle of canvas vertically, all the particles will be squashed into a single point. We created a pixel singularity. From there, the image will assemble as canava, reverse black hole, spitting out particles and decreasing entropy. I think this looks really cool. Which transition is your favorite Warp blocks assemble or particle print. Leave a comment to let me know. I hope you found some value and learned something new. Check out my other classes if you want to explore more creative coding or two D game development with vanilla Java sq, see later.