What do you want to learn?
Leverged
jhuang@tampa.cgsinc.com
Skip to main content
Pluralsight uses cookies.Learn more about your privacy
HTML5 Canvas Fundamentals
by Dan Wahlin
The HTML5 Canvas Fundamentals course provides an in-depth look at working with the HTML5 Canvas and shows how it can be used to display data, animate shapes, and perform many other useful functions.
Start CourseBookmarkAdd to Channel
Table of contents
Description
Transcript
Exercise files
Discussion
Learning Check
Recommended
Getting Started with the HTML5 Canvas
Introduction
Dan Wahlin: Welcome to the HTML5 Canvas Fundamentals Course. My name's Dan Wahlin with Pluralsight, and in this course, I'm going to walk you through the core fundamentals that you need to know to get started using the HTML5 Canvas to render graphics in your web applications. Now this is one of my favorite HTML5 technologies mainly because with some JavaScript, you can do some pretty impressive graphic rendering. You can do everything from games to audio and visual applications all the way over to line of business type of charting applications, and we'll look at some of those different types of things throughout this course. Now I like to blog about this technology as well as other HTML5 technologies at weblogs dot asp dot net slash dwahlin, and if you're on Twitter, feel free to follow me there as well as I tweet from time to time about various technical subjects. Now this is one of many courses I've done for Pluralsight. The ones listed here are related to the HTML5 Canvas in one way or another. The first one, Building ASP dot net NBC apps with Entity Framework Code First, HTML5 in JQuery, provides an end-to-end look at building an application that integrates various server side and client side technologies together, and towards the end of the course, I discuss how you can use the HTML5 Canvas to render stock charts. The JQuery Fundamentals Course goes into details about the JQuery API and JavaScript in general and shows how we can locate dom nodes, manipulate them, work with events, and even handle Ajax calls in a web application, all of which is applicable as you work with the Canvas and maybe get dynamic data into the Canvas. And then, finally, Structuring JavaScript Code is a course that shows different techniques and strategies you can use combined with some patterns that are out there that are adopted throughout the Web that provide a way to build more modular and maintainable JavaScript code. You're going to see throughout this course that the HTML5 Canvas API is very JavaScript centric. You will write a lot of JavaScript code, and at some point, you're probably going to want to structure that, make it more maintainable, reusable, and, in general, easy to work with, and that's what the Structuring JavaScript Code walks you through. Now to get the most out of this course, it's recommended that you have some knowledge of HTML and a solid foundation in JavaScript. Now you certainly don't have to be an expert as long as you feel writing JavaScript functions, defining variables, calling other functions, you should be absolutely fine, and I'll walk you through the different API's and how to use them in JavaScript so that you can render dynamic charts and other types of graphics using the Canvas API. In this first module, Getting Started with the HTML5 Canvas, I'm going to walk you through some of the basic steps you can follow to access the 2d Context and draw some basic shapes and other types of graphics. We're going to start off by talking about Canvas usage scenarios, including different ways that you might consider using the Canvas in your web applications. Then I'll introduce a step-by-step approach to getting started with the Canvas, put those steps into action with a Hello World example, and then provide an overview of the Canvas API, and we'll break those functions and properties into different categories such as functions you can use to draw shapes, work with text, perform transformations, and other types of features available with the Canvas API. So let's get started by taking a look at different ways you could use the HTML5 Canvas in your web applications.
HTML5 Canvas Usage Scenarios
In this section, we're going to talk about different ways that you can use the HTML5 Canvas in applications. From there, we'll talk about browsers that support it, and we'll talk about how you can write a little bit of JavaScript code to detect if a browser support the Canvas or not. From there, I'm going to show you some live demos of the Canvas in action. So as I mentioned at the beginning of the course introduction, the Canvas is all about drawing and rendering graphics. If you think about a painter, if they want to paint something, they'll typically get out an easel, put a canvas on there, we'll say it's a white canvas, and then they'll use their paintbrush, dip it in some colors, and paint different scenes. Well, if you think about the canvas API as being very similar, we're going to have a canvas, we're going to have a paintbrush, and using JavaScript, we're going to call different functions to render different shapes and draw text, and we can call some properties and set values to control things such as the color of what we're actually going to paint onto the canvas. Now there's a lot of great examples of using the canvas out there. One of the popular things it's used for nowadays is HTML5 games. There's a lot of games, and more and more are coming out every day that are HTML5 based solely on the Canvas, and that's because the Canvas performs very, very well. It's a pixel-based API, and in some browsers, it even uses the GPU so it's very fast and efficient. Now, of course, it's not only used for games. You can use it for multi-media applications. Microsoft, on their Beauty of the Web dot com site, had a really nice demo that shows someone doing an a cappella type song, and you can control the volume of the different parts, including the bass, the singing, and others, and you can actually drag around these little pictures, and these were live videos when you run it, and as you drag these around, they'll kind of snap back. They're on an elastic band, and everything that you see on here is actually using the Canvas. Pretty creative way to show audio and visual in the same map, and something that we really couldn't do with just HTML tags alone and JavaScript. The Canvas is pretty essential. Another thing you might see with the Canvas and a very popular thing nowadays for line of business applications or applications showing data is charting. Here's one from an application from another course I did, and this particular application showed charts from the Dow, the NASDAQ, S&P as well as custom quotes that a user might want to get. And you can see that it simply plots out the different data, and what's nice about this is no plug ins were used. It's all 100 percent HTML5 Canvas, which means basically one tag and a little bit of JavaScript, and that's really the nice thing about the Canvas is it's native to all modern browsers, and it's also very efficient in how it renders. Now there's a lot of browsers that support the Canvas. Pretty much every modern browser out there can be used. Safari, Firefox, Internet Explorer, Chrome, Opera, and even some others that are a little less popular, but as long as they're modern, it's a pretty good bet that you can use the canvas with them. Now how do you know though? What you can do is either write code on your own, or you could use what I'd recommend, and that is Modernizer. Now Modernizer is a JavaScript library that you can download for free from Modernizer dot com. It's a single script you can include in a web page, and you can use it to perform feature detection. Now, if you've been doing web development for a long time, you might have done browser sniffing in the past where we actually detect the browser such as IE6, IE8, Firefox3, 4, or whatever it may be, and that was a pretty error-prone way to determine what we could do in a particular web application. With Modernizer, we focus on feature detection. We can actually use it to say, hey, I want to know if this browser supports the Canvas or SVG or local storage or whatever HTML5 feature you may be using. Now this code sample here shows how if you've referenced Modernizer in a page, you can use it to detect Canvas support. So if Modernizer Canvas is true, then we can go ahead and start integrating our Canvas API code. Else, we can fall back to some other technology for older browsers such as maybe one of the plug ins such as Flash or Silver Light, and that's the type of process you'll go through to detect if a browser has support for the Canvas or not. Now you certainly don't have to use Modernizer, but it's used in a lot of other ways as well, and I highly recommend it. So let's take a look at a couple of demonstrations of the Canvas in action, and show you different ways it can be used.
Demo: Game Demos
If you're looking for examples of the HTML5 Canvas and different ways it can be used, you can head over to Canvas Demos dot com. They have everything from apps that use the Canvas to games to different tools as well as tutorials that you can walk through, and they even include some different libraries that will simplify working with the canvas to create different types of applications. So I'm going to click on games in this demonstration. I'm just going to show some really basic examples of how the Canvas can be used to render some games dynamically without any plug ins at all. No Flash, no Silver Light, just 100 percent Canvas in rendering graphics through the Canvas API. So I can scroll down, and you'll notice there's a lot of different games here I can pick from, but I'm going to come up here to the top ten games. And one of the nice things you'll find, especially if you go way back to the Super NES days, is we can come in and get into an NES type of emulator, and if I play it, it'll let me select a ROM. So we can come in, for instance, do Donkey Kong. Go ahead and load this up. Take just a moment, and then I can play the ROM just like we used to in the good old days on the different devices out there. Here we go. So soon the Donkey Kong should start throwing down the barrels, and I'm just going to use the arrow keys here to move a little bit. And you'll see that Fireball comes out just as you would expect. There it is, and we can run around, get hit by these, and you'll see I die if I hit it, and it works as expected. Can also come down. Let's do Pacman real quick. Now Pacman looks just like the original. So we'll hit enter to go ahead and start it. And it loads up, shows me my lives, the fruit I'm on, all that fun stuff, and we'll go ahead and start to play here, and it works just like you would expect. I can grab the different ghosts and do all that fun stuff, and we'll go ahead and try to have one of these guys get me. And you'll see I die there as I hit it just as expected. Lot of good stuff there. Now you can also do other things, more basic games like Chess, but here's kind of an interesting take on it. It's a little more 3D looking. So we can come in, we'll select a playing piece, move it out. Let's go ahead and move this guy out, and then we'll grab that guy. So you can actually play the entire game in kind of a 3D look, which is kind of neat, all using the Canvas API. There's a lot more demos on this site if you're interested. Just head on over to the site, and take some time to go through the different games that are available. Now the Pirates Love Daisies dot com is a game built by Andrew Skinner and a team. Andrew is pretty well known for his Flash type of work. This one, however, was built using 100 percent HTML5 Canvas. So this one actually has music. I have the speakers turned off right now, but as we load it, you'll see some flowers loading in. We can hit start game. This is kind of a Tower of Defense game. So we'll hit play. Now it's going to give us a little message here. We're going to be using Scarlet, and basically once this loads, a wave will come up. We can say where Scarlet should go, and basically we'll hopefully shoot the rats before they hit the daisies. And this entire game is also built using the Canvas API, and all the animations you see there you can do with things like Sprites. So that's a couple of examples of using the HTML5 Canvas, and there's a lot more out there. So if you want to do games, these are things that you can do without any plug ins at all, all built using standard JavaScript code. Now the demonstrations I showed here, they're pretty cool. Not really graphically intense, and don't have a ton of physics involved. There's two other very popular games that were ported over from mobile devices, and those include Cut the Rope and Angry Birds. So let's take a quick look at how those can also be rendered using the HTML5 Canvas. I'm going to go to Cut the Rope dot ie, and this game, if you haven't played it before, allows you to get some candy into the mouth of a little monster who's name I believe is Um Num, and Um Num likes to get this candy, and you have to strategically get it down to his mouth. So I'll show the intro here, and then we'll play just a little bit of the game. So we'll click on the cardboard box we want to start with, we'll click on a level, and if you haven't played before, you need to cut the rope so that the candy falls down, and you try to maximize the number of stars. So at the first level, it's pretty easy. We'll hit next, and we can move on to the next one, and this will basically let me get it, and, obviously, I should have cut it a different way to get that star as well, and you can continue going through all these different levels to cut this rope and make sure that Um Num gets the candy. So, obviously, I'm going to lose that level right there. Pretty cool because there's some very sophisticated physics going on behind the scenes, and all this is being rendered using the Canvas. Now we can also go to Chrome dot Angry Birds dot com, and this allows us to play the Angry Birds game. It'll take a moment for this to load up, but once it does, we can launch our birds into our pigs, get our points, and move on to different levels. So it'll take just a second or two to load up. There we go. It'll move onto the next level. We'll pick one, and let's go ahead and pick this first one here. Skip that. And just as you would expect from the mobile game, you can launch the birds, and we get some pretty nice physics that are involved. So these are some of the examples that are built in to the browser. No plug ins, and it really demonstrates how powerful the HTML5 Canvas is.
Demo: Engaging Applications
The HTML5 Canvas isn't only about games as I showed in the previous demo. You can also use it to build some very interactive and engaging websites, and do some things that simply weren't possible before without relying on plug ins. So to demo this, I'm going to head over to Beauty of the Web dot com, and click on amazing sites, and I'm going to scroll over a few to some that I know are using the Canvas. So one is Cut the Rope, which I covered in a previous demonstration. Another is Tron. If we go over to the Tron site, it'll actually load some music in the background you might be here a little bit of, and I can slide from side to side and view a comic book, and you'll see some nice animations that occur as I slide around through this comic book. You'll see some lighting here and other features. Provides a very nice interactive experience to view the comic book and do some things that really weren't possible before without Flash typically. Now to kind of prove that this is actually using the Canvas, I'm going to hit F12 to go to the developer tools, and I'm going to search for Canvas, hit enter, and go forward just a little bit, and you'll see right there that we are using the Canvas tag. Some other sites out there as well. In fact, the next one up is a site with Mike Tompkins. Now, he basically sings all the parts of a song, including the bass, the synthesizers, and the vocals. So let's go ahead and visit this, and this entire site is showing audio and video and using the Canvas. Now what's nice about it is these videos that are playing, you'll see as I drag these around, it's kind of elastic, and the Canvas is being used to render all of this. Now down here if I turn all these off, you'll see everything is kind of shrinking. Now I'm only left with the bass. I'll turn that up just a little bit. So here, you have the bass, and we can turn that off as well. So basically as I control these, you'll notice it gets bigger, and it's a really creative way to actually show audio and video using the HTML5 Canvas. So that's another example of how the HTML5 Canvas can be used that's not related to games but definitely adds that pizzazz or engaging experience for your end users without relying on any plug ins.
Demo: Charting
In addition to using the HTML5 Canvas for gaming or to build engaging and interactive websites, you can also use it for line of business apps or really any app that has data that needs to be charted. Here's a sample application called Account at a Glance. This is something from another course I put together for Pluralsight that provides and end-to-end look at building an application, and one of the technologies covered in that course is the HTML5 Canvas, and you can see it's used to render some stock quotes. So I can go in and get different quotes, and it will chart those, and although this there's simulated data, you can certainly use it for real data as well. And also drag down, for instance, the NASDAW, we have the Dow, and I can even do the S&P 500 if I wanted and see charts of these different markets and the different quotes that we have that a user might want to get. Now, this happens to be using a library called Flot, which makes it very, very simple to render data using the HTML5 Canvas. Now I'll discuss some of the different Canvas libraries available at the end of this course, but just to show you a few examples up front, if we go search for Flot and Canvas, we'll go to the site where you can get this script, and if I click on examples, you'll see a couple of different graph types that we can actually render using the Canvas. So here's an example. You can say we have some bar charts, some lines. We're plotting some points, and doing even some really nice little curves with filled-in areas. And if we go to the bottom, we can stack charts, do it without stacking. We can get bars, lines, and even steps if we wanted. And all this is being done using the HTML5 Canvas, and what's nice about that is any browser that supports the Canvas including mobile browsers, iPad browser, and so on and so forth would be able to render this type of a chart without requiring any type of plug in at all. And let's face it, with the devices we have coming out nowadays, that's actually becoming more and more of a big deal. So that's a quick look at some of the different charting types that you can plot with the HTML5 Canvas natively in a browser.
HTML5 Canvas Fundamentals
Now that you've seen different ways that the HTML5 Canvas can be used, let's jump into some of the fundamentals that'll help you get started with it. So first, let's discuss some of the key features it offers. The Canvas, as I mentioned earlier, provides a drawing surface. You can think of it just like a painter's canvas that we're going to draw on using either some pencils or pens or more likely a brush, and we can do all kinds of things with it because it's pixel based. Now, it's not vector such as scaleable vector graphics, SVG. It is rendering pixels. So if you want to zoom in, zoom out on it, you're going to have to take into account the scale factor yourself and render the graphics as appropriate. Now you can draw all kinds of things with it, shapes, lines, gradients. You can even embed images and video, and I showed some of that in the previous demonstrations, and it really provides for some nice interactive experiences that you can build if that's what you'd like to do with the Canvas. It does provide built-in support for transformations. You can do things such as rotate and scale, and I'll show a little bit of that as we get into the course more, but there's no built-in support for animation. So if you are going to be using the Canvas for gaming, you're not going to be able to tie in to some type of animation library like some frameworks have such as Silver Ladder, Flash, or other plug ins that are out there. You're going to have to take care of the animations yourself and write a game loop, and in the game loop, you'll be firing some type of timer every certain number of milliseconds, and when that fires, you'll call an update function which will then move the pixels. So you'll have to erase the pixels that were there, clear them out, and then re-render those pixels, and we'll talk about some of that as we get a little further in the course. Now to actually get started with the Canvas, you need to add a Canvas tag into your HTML document. So the tag definitely matches up with the functionality, and you'll typically give it an ID, and they're going to want to set the height and the width, and you'll want to do it the way that's shown here as opposed to using CSS Styles or CSS Classes. I've found across pretty much all of the modern browsers if you do it with CSS, it won't render as expected so it's pretty important that you define a width and a height attribute on the Canvas tag. The actual steps to get started using the Canvas are shown here. So first off, to find the Canvas element. Well, that's pretty easy, as you saw in the previous slide. From there, we're going to be jumping into JavaScript. The only HTML you'll do with the Canvas is defining the Canvas tag. From then on, you're going to be writing a lot of JavaScript. So first thing you'll do after defining the Canvas is locate the Canvas ID, and you could use JQuery, you could use Document, get element by D. We can then access something called the 2d Context, which I'll show a demonstration of that coming up, and then, finally, once I get the 2d Context, which I like to think of as a pen or a brush, I can now use that 2d Context to actually draw onto our Canvas surface. And now I can draw rectangles and arches and all kinds of different lines and things of that nature. Now, let's walk through these steps real quick before I actually put a demo together for you and show how these steps can be used to render some basic drawings on the Canvas. So first off, we're going to go in and define the Canvas. Now when you do this, any content that you put between the start and the end tags would be displayed if the Canvas is in support. So you actually can have a nice fall back, and if you wanted to resort to something that you know browsers will support, such as Flash, then you can actually define something like an object tag and have an SWF or whatever it may be to act as the fall back. That way if a browser doesn't support it, you can go ahead and still show some type of rendering into the web page. So that's kind of step one. With step two, we want to go ahead and locate the Canvas ID, and in this example, I'm just using the standard window onload. Now if you're using something like JQuery in the document ready, you can do the same type of thing, of course, but basically once the dom's been loaded, you'd be ready to find the Canvas by ID and go ahead and work with it. Now once we found that, we can then get to the context, and it's a special type of context called a 2d Context, and at this point, that's all we have actually for the Canvas. One really important thing with this is that case does matter. I've accidentally tried it with an upper case D and found that it doesn't work so well. So you do need to put 2 with a lower-case d to get the context. So get context is a function off of the Canvas object. Once we have the 2d Context, we're ready to go. We have the Canvas, which is like our painter's canvas, and now we can use the 2d Context to actually start to draw on to the painter's canvas. So now we can go in and do things such as setting the fill style. In this case, we're going to set it to red, and then in this simple example, I'm going to fill a rectangle. This is going to say start at 0, 0. The upper left-hand corner of the Canvas is 0, 0. We want it to be 200 pixels on the width and 100 pixels on the height, and that's the basic steps you'd go through to locate the Canvas, get the context, and then from there, it's up to you to render different types of shapes. So let's jump into a demonstration. I'm just going to do a Hello World type demo, and see how we can put these steps together and render different types of things to the Canvas.
Hello World Demo
Now that you've seen the steps that can be followed to get started using the Canvas, let's go ahead and put those steps into action and do a demonstration. To demonstrate using the Canvas, I've created a simple HTML5 document that you can see here, and I'm going to follow the steps that I outlined in the previous section of this module. So step one was we need to define the Canvas element. So let's go ahead and add some comments along the way. And that's one of the easier steps performed. So we'll simply define a Canvas, we'll give it an ID, we'll call it My Canvas. Lets give it a width of say 600, a height of 400, and if we run it at this point, you won't be real impressed because it's going to blend right in with the page so you really can't see the dimensions, but actually it should be right around in this area. Now to make it visible, it's pretty easy. We can actually just add a style, and we can do in this case a light grey. Let's run it again, and now we can actually visualize the height and width of the Canvas. Makes it a little bit easier to work with, especially when you're just getting started and want to play around. Step two is all JavaScript. In fact, pretty much everything you'll do after defining the Canvas element is involving JavaScript. So I'm going to come up into the head section. Let's add a script. And with that script, we'll come on in, and I need to handle accessing the Canvas, getting to the context, and rendering, but I can't do that until the Canvas is loaded up in the dom. So if you're using JQuery or some other library, you can handle the dom content ready, but I'm just going to do window onload, and we'll assign that to a function that'll get call when it loads. So in here, we now need to go to step two, which is find the Canvas. Step three is going to be access the 2d Context, and then step four is going to be render some graphics. So to actually find the Canvas is very simple. We can use document get element by ID. So we'll make a canvas variable, and we'll grab our My Canvas ID and paste it in, and that's pretty easy. So step one is now taken care of. Now step two is also very simple. We can define a variable. I usually call it CTX for context, and we'll now take our Canvas object and we'll say get context. Now we can't just pass empty parentheses. We need to say what context, and we want the 2d Context. Now it's really important, and I mentioned this earlier, that you leave it lower case. I've accidentally slipped in an upper case, and you'll spend a little bit of time debugging thinking something else is wrong with your code, and all it was was you didn't case it properly. So case does matter. Make sure you do a lower case there. And that's it. We're ready to go. So now we can use this context, and I like to think of this as the pen or the brush if you were a painter or an illustrator that you want to work with. And so now that we have the pen or the brush, we can now use it to render and draw to the Canvas. So I'm just going to render a very simple shape. We're going to do a very Hello World type of example. I'm going to render a rectangle, and then we'll render an ellipse. So to render a rectangle's pretty simple. We can say context dot fill rect, and give it the x and y starting position. Now when we run this, let me comment this out and run it one more time. The Canvas xy position starts up here in the left corner just like most screens. So 0, 0 is up in this area, and then, obviously, down in here we'd be at a width of 600 and 400 in that approximate area. So what I need to do is say where do I want this rectangle to be rendered in the overall Canvas. Now, if we want it up in the left corner, we can do 0, 0. If we wanted it somewhere near the middle, then we could do something like 300, 200. And now we need to say what's the width of it. Let's say that we want 200 on the width, and we want 100 on the height. So if we were to document this, we have the x, the y, the width, and the height, and that's what we're doing. Now if we run this, we didn't tell it what color, but let's see what happens, and you'll see we get a default color. So you can see it defaulted to black. Fortunately, it's very, very simple to actually control what type of color we want to show, and we can do that. If think of a painter, they would dip their brush into some color, and then paint with it. Well, we can dip our context by calling fill style, and giving it a color. So let's go ahead and give it a color of say green. What that'll do now is now the brush is green, and pretty much everything that we do from here on out will be green. So let's come up to run, we'll launch it, and now it should change to green, and you can see we've now rendered a simple rectangle. Alright. Now the last thing I'm going to do for this Hello World demo is let's do an ellipse. Now if you've other graphics API's such as GDI Plus or Flash or something else, you might expect you'd have something like a fill ellipse or maybe a fill circle or something simple like that, and it's actually not the case. It's called arc. Now what arc does is it makes us define several different things. The first is we need to go in and actually define x and y points. So let's do, ah, let's go down to say 100 and 100, and that's our x and y. So I'm just going to add a comment above this. So we'll say xy. The next thing we're going to add is what's the radius of the actual circle. Then we do the start angle, the end angle, and then do we want it to be clockwise or anti-clockwise. So I'll just put anti-clockwise. Alright. So in this example, we're just going to do a simple radius of around 50. Now we need to give it a start angle. Now I'm going to start at 0, and I'm going to go all the way around. So we're going to do 2 times math dot pi, and that'll make a complete circle and really make an ellipse, a circle that's complete. And then for anti-clockwise, we're going to say no, just do it normal. It won't matter in this case actually. Now if we run this, you won't be real impressed because you're not going to see it. You'll notice it should be up in here somewhere, and there's nothing to be found. The reason for that is we never actually told it that we want to fill it. So all we have to do to finish the arc is say fill. It's pretty easy to forget that actually because with fill rect it does all that in one step, but there is no such thing as fill arc. So we actually have to make an arc and then fill it. Now what colors are going to use? Well, currently our brush is dipped in green. So the rect is going to be in green, the rectangle and the arc is going to be green. So let's go ahead and run this. And there we go. We now have our simple circle or ellipse, and we have a rectangle. Now it's really easy, again, to change the color of this. We can come in, and if you don't change it, the brush just basically stays green, and so everything you render on the screen is green, but we can follow the same principle, and let's say we want navy. Now we'll go ahead and run it, and we'll get a navy circle up here with our green rectangle. So that's our Hello World example that follows the steps that I outlined earlier. We define the canvas, give it an ID with a width and a height, and then I set the background color just so we can see it a little bit better. You certainly don't have to do that. From there, we went in and found the Canvas. We accessed the 2d Context with, as I mentioned, I like to think of as the brush. We set the brush to green. We fill a rectangle. Given it where to start on the xy coordinate system and the width and the height. We changed the brush to navy, and then from there, we draw an arc saying that we want it to be 50 as far as the radius goes. Now, obviously, if we want a bigger one, we can simply increase the radius if we'd like. From there, we call fill, and that's it. From there, the Canvas takes over, and this now renders those pixels to the screen. So that's a wrap on this Hello World demo that shows how to get started using the HTML5 Canvas.
Overview of the Canvas API
The HTML5 Canvas provides a rich set of functions and properties that you can use to provide different types of rendering functionality in your web pages. Now up to this point, you've only seen some of the basics. I've shown how to render, for instance, a rectangle and a circle and even how to control the fill color, but there's a lot more that you can do with the different functions and properties provided by the API. In this section, I'm going to introduce some of the key functions that we'll be talking about in modules that will be coming up and categorize those into things such as how do we do shapes, how do we work with text, and we'll even talk about something called transforms. So let's go ahead and jump in and take a look at what the API is composed of as far as the functions and the properties go. This is a list of the different Canvas API functions that are available to use. Now the first thing that struck me when I saw these was that, number one, all of them can be fit on one page, which makes it pretty approachable as an API. It's not like you have to learn this massive book of function after function after function. And the nice thing is is once you categorize these into things like how do I render shapes and lines, text, transforms, and others, it's actually a pretty approachable API to work with. So as you glance through here, you'll see that we have everything from color stops with gradients, we can do arcs and different types of curves, including quadratic curves over here, we can work with text, and we can do different types of transforms, and I'm going to break those down into a more manageable set of functions in just a moment. Now in addition to the functions, we also have a lot of different properties, and these properties are typically used to style before we actually fill a rectangle, draw an arc, or do something like that. So you'll notice that we have the fill style, which we looked at in the Hello World demo earlier. We can set a font, work with alpha transparency type of things, height and width of the Canvas, we've already looked at, work with text, and even do some things with shadows and control how lines look as they're rendered. If we were to take the different functions I just showed and kind of break them down, it would look something like this. Here's an example of the different line and shape functions that are available in the API. So we've looked at a few of these such as the arc and the fill rect and the fill as well when we did the circle, but we haven't looked at things like begin path, we haven't talked about how to clear a rect or do clipping or even draw lines or quadratic curves, but we'll be covering some of that in the upcoming modules in the course. So that kind of breaks down some of the key functions related to lines and shapes that you might use as you render to the Canvas. Here's some of the text functions, and you'll see it's pretty simple. We can draw some text, we can measure the size of the text, and we can stroke the outer border of the text if we wanted using these three functions. Pretty simple and manageable to learn and work with. We can also perform different types of transforms, and transforms are useful when you want to manipulate a particular item on the Canvas, do that manipulation, and then go back to where you were when you started. So as an example, you might save the state of the Canvas, maybe you'll rotate some text, and then you're going to restore the state of the Canvas so that everything looks normal again, and I'll talk about some of the different techniques you can do with this coming up. But these different functions can be used to perform different types of transforms in the Canvas. Now there's much more than this. You can even get to the pixel data, for instance, of the Canvas using something like get image data. You can work with a lot of different curves I mentioned. I mentioned briefly the gradients, and we'll be covering some of those as we go through the upcoming modules in the course. But that's a quick look at some of the different API functions and the properties that are available with the HTML5 Canvas.
Demo: Canvas API Documentation
Now that you've learned about some of the different API functions and properties for the HTML5 Canvas, let's look at the actual definitive source out there on the Web from the group that defines these different API functions and properties you'll be using, and the group that's working on it is called the Web Hypertext Application Technology Working Group, or you can just go to what wg dot org, and when you get there, you can click on HTML, and the third item down, Symantec structure and API's of HTML documents, will get you into the details we need. Now you can scroll around, but it's generally easier just to search for Canvas, and there we go. Here's the Canvas element, and from here, you'll notice that we can drill into all kinds of things about rectangles and text and paths and images and much, much more, and they also have examples. Now I'm going to go to the top starting point of this, and as I scroll down, you'll notice that different things will be shown as far as the browsers that are supported and which browsers implement some of the different functions and API's that are shown here. So as I keep scrolling down, we'll actually see these little green boxes, and you can mouse over to see. So it's a really nice area to go to to learn more about the actual API functions and the properties, but also to get samples and see some of the new stuff they're working on, what browsers actually support it, and what you're able to do with the Canvas. So that's a good place to get the actual details from the people involved with the spec. Now another good source of examples is W3 Schools dot com, and if we go there and click on learn HTML5, on the left side here, we'll have the HTML5 Canvas. And this is pretty nice because we can actually scroll down, gives us a nice little tutorial on how to get started, very similar to what I did earlier in this module, and provides some different try-it-yourself demos. Tells about the Canvas tag, and then here's the complete 2d reference. So drilling into here, we can now get all the different properties, the different functions you can work with, and, for instance, if I want to learn about the quadratic curve, too, we can click on that and get a nice little demo, and we can even run it live, and it'll show us a demo that we can then modify over here and play with. So this is also a nice little source of learning more about these API functions and properties, especially as we're getting started. So that's two areas you can definitely take a look at. You can either go directly to the source and look at some of their demos and examples, or go out to sites such as W3 Schools dot com.
Summary
In this module, you've seen how the HTML5 Canvas can be used to render graphics to a screen without relying on plug ins such as Flash, Silver Light, or others. The HTML5 Canvas itself is very flexible in how it can be used. We looked at some examples of gaming, audio visual, engaging type of applications, and maybe not as exciting but very, very important for line of business applications charting, and so you can take different types of data and actually chart that without relying on these plug ins that typically we've used in the past. Now as we went through some of the features of the Canvas, you saw that really all you do from an HTML standpoint is define the Canvas tag. From there on out, it's all JavaScript based, and we're going to be using JavaScript to find the 2d Context and then perform the different types of drawing operations using the API functions and the properties that we discussed toward the end of the module. So that's a wrap on the fundamentals of getting started with the Canvas and the different ways it can be used. Now we're going to start to jump into more of the API functions and see how they can be used to render different types of graphics.
Drawing with the HTML5 Canvas
Introduction
In this module, we're going to jump into the different functions and properties that can be used to draw different types of shapes, lines, and other objects onto a canvas dynamically with JavaScript. So, I'm going to start off by talking about some of the more familiar shapes such as rectangles, ellipses, circles, and arcs. And explain the API functions you can use and how we can style those and add color and other items into those using properties. From there, we're going to go into lines and talk about different types of paths such as Bezier curves and quadratic curves, and show some different types of shape that you can draw dynamically there. From there, we'll switch gears and talk about text, images, and videos. So we'll first start off by talking about how we can render just some simple text. We can actually measure text to see how big it is, to make sure it fits in a certain area. We can then also embed images, if we'd like. And we can even tie the HTML5 video tag into the canvas to do some pretty creative types of effects and I showed a pretty cool example of that in module 1 in the different HTML file canvas demos that I did. So let's go ahead and jump right into the first set of APIs and that relates to rectangles and ellipses.
Drawing Rectangles and Ellipses
Rectangles and ellipses are obviously some of the more common shapes that we might want to draw under an HTML5 canvas whether it's for game, charting, or other application. So in this section, I'm going to focus on the different functions and the properties you can use to render these types of common shapes. Now earlier in the first module, you saw a complete set of all the functions available. And at first glance if you're new to the canvas and really have never touched any of the functions, it might feel a little bit overwhelming. So what I've done is broke this down into the functions that relate to each sections. So we're going to talk about rectangle and ellipses in this section. And you could see there's really not that many functions available that you have to worry about to draw these types of things, in facts, it's pretty easy, you'll see. So first off, there is no ellipse or circle function built into the canvas but there is something called arc and arcTo. And those can be used to do the equivalent of a circle or different types of shapes, ellipses. We can also do things with rectangles. We can fill the rectangle, clear it, we can just draw it a generic rectangle which could be filled or stroked with an outer border color and we can even stroke a rectangle. So some of these functions such as stroke and fill, they can be used to fill a rectangle that might have been rendered or fill an arc that might have been rendered. Whereas things like StrokeRect, obviously will draw a border around the rectangle, whereas fillRect will automatically fill with a specific color and you'll see you'll default to black if you don't specify a color. So let's take a closer look at some of these functions and what the parameters are that you can pass into these. So here's a quick look at the rectangle functions. And you could see that they all are pretty simple because they take X, Y coordinates of where to start the upper left corner of the rectangle, the width of the rectangle and the height of the rectangle. So they all take the same exact parameters, so it's very, very simple to get started with. The clearRect is used normally when you want to clear a canvas or a section of a canvas, for instance you might have a black that's 100 pixels wide by 100 pixels tall, and you want to clear whatever is in the specific area out, where you could use clearRect to do that. FillRect does what it says, if fills a rectangle with a specific color that you'll provide. Rect just draws a rectangle but if you only use it on its own, you won't see much, you need to either stroke the outer border of it or fill it with the stroke or the fill functions. And then finally, strokeRect is a little bit different than fill. Fill is actually like coloring in the entire contents of the rectangle. Whereas, strokeRect only strokes the outer border or renders the outer border with a specific stroke color which we'll talk about. So, we can set the colors of the fill or the stroke using a fill style or a stroke style. So you can give an RGBA type color or you can give it a hex, or you can even just give it a name color if you want such as red. And what that will do is as we call fillRect, as long as we set the fill style first to something like red, then fillRect will automatically fill using that color. So I like to think of it as we dip the 2D context that we talked about in the first module into a specific color, and we do that using fill style or stroke style. Then we go ahead and perform the actions such as fillRect or strokeRect, and that's like picking up your paint brush, moving it up to the canvas and now actually filling it in or just draw in the outer border of the particular rectangle in this case. Now we also have different arc or ellipse type functions. Now as I mentioned there is no ellipse or circle functions per se, but you can accomplish the same thing with the arc or the arcTo. So the arc is a little more complex and you can see it takes the Y, X coordinates of where to start drawing the circle. Now, the circle is rendered by default from the center point of the circle. And how far it goes out is determined by the radius. And so you'll say I want to go in 100 pixels by say 100 pixels, and we go over 100 down 100, that we'd render here. And then if I had a radius of 50, we'd get a circle about that big right in that area. Now the start angle is where do we want to render the circle and start drawing? And we can start at zero for instance, or we could draw some other type of shape somewhere else if we wanted. The end angle is where do we end the circle as far as the angle of that and we probably want to go 360 degrees obviously if we wanted a full complete circle. And then anti-clockwise is do we want to render clockwise which is the default or anti-clockwise which would be go this way and that's useful when you want to do like half circles going this way, this way, things like that. Now, arcTo has the X and the Y coordinates and the X and Y2 coordinates and a radius. So we're basically going to have 2 points that we're going to specify, and then the radius will allow us to draw an arc from this point here, X1, Y1 over to X2, Y2, and I'll show an example of that as we get into the demos here. Now the same type of properties can be used if we want to come in and call fill on an arc then by default, it's going to use black unless we specify otherwise. So, we'll come in and normally define a fill style of say red or green. And if we just want to stroke an arc, we can call arc to define the arc first, then we call stroke, and based on the stroke style that we set, that would be the color that would be used to outline the border of that. So let's go ahead and jump into some examples of using the different rectangle and arc type functions with the HTML5 canvas.
Demo: Simple Bar Chart
Let's take a look at some of the different rectangle APIs that are available and how we can use those in different ways. So to start off, you'll see that I already have a canvas defined and I have a window on load that I'm going to use. So we'll do the normal find-the-canvas routine, so we'll do document get element by ID, and we'll get the context. So we have our paint brush that we can render with and we'll get the 2D context. All right, so from here in module 1, I showed an example of how you can draw a rectangle. So I'm going to show that real quick but show a couple of options you can do with some other APIs. So one of the first things we can do is use the context to actually come in and fill a rectangle, and we can give it at the X, Y coordinates and where it should go. So if we want to go for instance 10 in and maybe 50 pixels down, we can then come in and give it a width, and let's go ahead and say 100, and maybe 200 for the height. And what that will do, because I haven't defined anything else, is use black as the actual color. So if we go ahead and launch this in Chrome, we'll see that we get the very simple rectangle on our canvas. Now of course we can come in and we can use different properties and one of those is the actual fill style. So let's go ahead and make this a navy blue, we'll save that and run it again, and we can change the color. So that's very similar to what we saw earlier. Now we can also come in though and do strokeRect. And if we run this, because I didn't define the actual stroke style, you'll see that when we launch it here, we just kind of get what would be a black type of stroke. And let me go ahead and move this up just a little bit, let's run that one more time, and there we go so you can see that we have the stroke coming down but we haven't define the color. So we can simply say stroke style is navy, and now once we run it, you'll see that we kind of get a navy blue type of stroke that's going on here. All right, so that's an example. Now, you'll notice it's cut off a little bit and that's mainly because the height is 200 and you'll notice that the rectangle is 200. So we can of course easily change that and we'll launch it again and now we should see the whole thing that it strokes. That's kind of the difference between them. Now, what we can do is combine these, so I can actually come in and let's say that we do want a fill style and we want that to maybe be green, we want the stroke style, let's change that to black, and what I can do is actually do both. So we can come in and say fill red and that's going to use our fill style of green, but we can also come in and say stroke. Now, one way we could also handle this is to just say, rect and that will draw a rectangle but then we'd have to call the fill and the stroke. So we fill it and then we stroke it. But let's go ahead and go back to what I had first and we'll show that. All right, so let's go ahead and run this. And you'll see that we now have the green but we don't actually have much for the stroke that we can see. So we can come on in, and we can do a strokeRect. We'll give the exact same dimensions and we'll run that. And it's a little bit hard to see but you can see that it almost looks like a shadow around the outer border of this. So that's an example of some of the basic things you can do. And of course, as I mentioned we can even come in and do something like this where we define a rectangle but we don't actually fill it at the definition. We just say, here's a rectangle, now let's fill it, and stroke it. So we'll go ahead and launch this now. And you'll see we get the exact same type of output. So we can define it that way, we could use the fillRect, we could use the stroke, we can do those types of different things. So that's just a simple example of getting started with some of the different APIs that are available. Now let's do something a little more realistic though. So what I like to do is create a really simple bar chart and demonstrate using the APIs available for rectangles to do something a little more creative and involved. That's going to be a very straightforward and it will be easy to follow for you. So we're going to start off by coming in and I'm going to create an array, and let's call the scores, and the array is just going to have some different values so let me throw in a couple of test scores here, something like that. And what we're going to do is iterate through these scores and each one will show a bar. So the 100 will have a higher bar, the 90 will be slightly lower, and so on, and so forth. And then each bar in the chart is going to have a width and let's go ahead and set that to about 50. And then we have to start, where does the first bar go? I'm going to call that currentX and you're going to see in a moment, I'm going to increment that by a few pixels so that we don't have bars overlaying each other. Now the final thing I want to set is what's the base of where the different bars are going to start from? Now, this is going to present an interesting little problem because you're going to see that with a rectangle API, everything draws from top down but if you think about a bar chart, I actually want my columns to be at the bottom and then go up. And so we're going to have to do a little bit of just some basic math to handle this. But we're going to set that-- we want 200 pixels down to be the starting point of our particular chart. Now the next thing I'm going to do is let's go ahead and set the fill style of each of the bars to green and what's nice about this is as I draw each bar, I certainly could do different colors for instance based on a range, maybe the-- everything in the 90 range is a green, and everything in the 80 range is purple, or something like that. But we're going to go ahead and do green in this particular example. Now next thing I'm going to do is iterate through the scores. So let's go ahead and iterate while the I variable here is less than the score.length, and we'll increment by one. All right, so there's our simple loop. Now from here, I need to grab the actual score because that's going to represent the height of each bar. So we're going to assume that 100 is the highest and then in this case 45, it looks like, would be the lowest. So, I'm going to grab the height of each bar and we're going to do that by simply going into the scores, we'll grab scores I. From here, I now have everything I need. I have the starting X position of the bar and I have the height of the bar, as well as the width of the bar. So now, we can use the fillRect by simply saying context.fillRect as you saw earlier. And I'm going to give it currentX, and I'm going to give it the height, the width, and then the H which is our scores I. All right, so basically we're going to start off by saying where it gets positioned. We're going to say currentX, we're going to start at 50, do the height, do the width, and then the height of the bar is going to represent how high it goes. And in this case, the height is going to represent the Y. Now, you're going to see in a moment, this is going to work out quite like we want but we'll come back and fix it. Now as we loop through, we need to move our bars starting from left and then move them over to the right. So we're going to take currentX, and we're going to grab the width which is 50, and let's go ahead and just add a few pixels, this will be the gap that shows between the bars. And we'll go ahead and save that. So let's come up and run it. And let's see what we have at this point. And you'll see that we do get some bars and it's a start but it certainly not what we're after. This bar here for instance which was the 90, I believe, should obviously be somewhere down here. So if the base was here at 200, this bar needs to be flat with this one so that it has a little bit of a gap and then obviously this one up here should actually be right in that area. So we need to subtract the difference from the 200 and the height here, and get this difference and that's how far down we want to start rendering. So that's pretty easy to do we already have our canvas and we could easily say canvas.height to get that. So let's come in and say canvas.height and then we can to subtract off the score which is the 100, the 90, and so on and so forth, off of that. So let's run it, and there we go, it looks pretty good. So we have our base here, we now have our bars lining up as appropriate, and we have our nice little gap between them, and as mentioned, we could easily change the colors if we wanted by simply adding a little logic into the score here. And if it was in, like I said, the 90 to 100 range, maybe we do green and we'd simply change the fill style in the loop based on some different logic. What if there was a problem with this? Let's do a quick debugging technique here. Fortunately, tools like IE9, or Chrome, or Firefox with Firebug make it pretty easy to find issues. So let's say that I for instance accidentally snuck a bar on here which of course would be wrong. How do we find out what's wrong easily, because, as you're writing a lot of canvas code, and as we get further along in the course and get more and more code going, it's definitely going to be a little tricky to debug unless you know some different tricks you can use. So we'll come in and I'm going to launch this again in Chrome. And what I'm going to do here is you'll notice nothing rendered and that's 'cause of that bar I threw in there. So what I can do is hit either control shift I or F12 either way. And this pulls up the debugger type tools. And I can come over, and right away down here on the bottom right, you'll see I have one error. And if I click that, it says we have an unexpected token. And if I click on the rectangles HTML line 14 over here, we can get the actual area. So this always follows the error. And we can see this line right here is the problem, and it makes it pretty easy to now go in and fix that. So let's go in and do that, take it out. Let's run it again but I'm going to go back into the developer tool here. And let's say that we wanted to actually debug this a little bit. But we can actually click on scripts and I can select the script, I only have one right now because the script is inline with the HTML and you can see it. So if I wanted to actually set a breakpoint and debug this, I can click over here in Chrome and it works very similar in IE as well as Firebug-- especially Firebug is very, very similar. And now I can go ahead and refresh the page, and you'll notice that my breakpoint gets hit. Now from here, these are my step into, step out, step over, or it can hit some Hotkeys. So for instance, I can hit F10 to step over, I can hit F11 to step into, and do those types of things. So I'm going to go ahead and just hit these guys over here and you'll see the different hot keys. And we'll go ahead and step in here. And now we're obviously in the loop and there's our first one, it just got drawn. And you'll see as I click, we can actually see those render. So that's a really nice technique to know, because if you get an error, you can hit F12 or control shift I. And you can go in, see if there's an error over here, and it makes it very easy to identify where that error maybe located. So that's kind of an initial example of using the HTML 5 canvas, do something a little more useful. And as we move along in the course, we're going to keep building on these concepts and I'll show other things we can do as well.
Demo: Simple Bar Chart with Transforms
In the previous demonstration, I showed how we can use different canvas APIs to render rectangles, and even do some basic charting. But as we did that charting, we saw that when you render a rectangle, it starts at the upper left hand corner of the rectangle and draws down which presents a little bit of a challenge 'cause we have to account for the gap if you want the chart to render from kind of the bottom up. So in this demonstration, I'm going to show another technique that we can use that relates to something in the canvas called transforms that would do the same type of thing but make the code a little bit more simple from the standpoint of not having to subtract off that distance between the bottom and where that rectangle renders. So you can see that we've already created a canvas and we've loaded it up, we have our context as well as our data, where are we going to start, and some other items here. And what I'm going to do now is come in and we're going to use the canvas' translate function to actually say where we want to start rendering this type of data. So the first thing I'm going to do is I'm going to make this chart just a little bit bigger here and we're going to go to about we'll say 600 by 400. Now what I want to do is the context has a transform type of operation you can call called translate. And what translate does is an X, Y coordinate translation. So it will actually move where you're rendering down. And so we're going to actually go to around 375 and 200. So we're going to go 375 over 200 down. And that's-- what a translate does is actually positions where we're going to, in this case, start drawing at. Now from here, I want to go ahead and rotate the canvas. Because ultimately, what I want to do is start rendering from a baseline and draw up. Well, by default as you saw on the previous demonstration, rectangles draw down. So I need to flip this over 180 degrees around and we can do that through a rotate. So I'm going to say, let's rotate this and if we did 2 times math.PI, that would be 360 degrees around. So, 1 times math.PI is 180 degrees. So we're going to go ahead and flip it over and go 180 degrees around. Now from here, it's actually pretty simple. We can come in and we can set up for instance the fill style and I'll do green again like I did in the previous demo, and then we can loop through the actual scores so let me go ahead and set up a loop again and we're going to go, well, I is less than scores.length. And inside of the loop, what we'll go ahead and do is fill our rectangle. We're going to grab our currentX and we're going to start from zero, though. So we're, basically going to be starting at the top of the canvas but because we flipped the canvas over 180 degrees, it's going to look like we're rendering from the actual bottom. And we'll make the width the same, 50 pixels, and we'll grab the scores I. So really what we're doing is we're drawing from zero on the canvas down but because we flipped it, it's going to render and make it look like we're drawing from the bottom of the canvas up to whatever our score height is that we're going to apply it to the height. Now from here, we go ahead and increment our X by-- we'll do 10 pixels again and we're pretty much ready to rock and roll here. So we've basically set up our scores, we then are going to translate a different drawing position, I'll kind of play around with this in just a moment to show you why we're doing that. We're going to rotate the canvas or flip it over 180 degrees. And then from there, it's pretty much the same. Now what's going to happen is it's going to do 100 but because we flipped this over, the bar for 100 is going to be on the far right instead of on the left. So we can easily do an array.reverse to get this going but let's go ahead and give this a shot and see what we have at this point. All right, now it looks pretty much like what we just did, however, it's just flipped over-- this is actually now that what was the top of the canvas, this is the zero, and now we're drawing up. So it kind of makes it a little bit easier to not have to worry about the math but of course there's a little bit more overhead in this case because we are doing a rotation but it's a one time rotation so it's not like it's that big of a deal. Now, if we wanted to look exactly like the other one, the 100 as I just mentioned is actually on the far right because we flipped this over with the rotate. So if we launch this again, you'll notice the biggest bar is over here to the right, and then there's the 90. So actually the array item 0, 1, 2, 3, 4, 5 are now going from right to left and obviously we're used to seeing those probably from left to right if that's what we actually wanted if we want to mirror the data. So that's pretty easy to fix, we can come in and say, scores, and we'll do a reverse here, and that'll simply reverse the array around, and there we go. So now, it looks exactly like we did in the previous demo but I'm not having to worry about subtracting the height. Now whether or not you want to go with this approach, you want to go ahead and just do the math and draw all those down as in the previous demo that would certainly be up to you. Really the point of this though is to show that with a canvas, this provides a good demonstration of using things like the translate and the rotate. Now, real quick, let me go ahead and take off the translate here and show you what happens when we run it. And you notice you don't see anything and what happened is the zero is up here, it literally got flipped, and we're basically off of the screen at this point. So the reason I'm doing a translation to go to over 375 and 200 is so we can see it. So let's go ahead and mess with this just a little. Let's go over a 175 to 100, we'll launch it again, and now notice that some of the canvas is on but we're actually off the screen over here. And that's because we need to translate it even more so we'll go ahead and go back to what we had, 375 and that turns out to be the magic number. Now we could certainly calculate this based on the width of the canvas and do some division there, divide it by two and maybe add a little bit. But by doing this, it now works and we get the actual canvas, and it makes our math a little bit more simple when it comes to filling the rectangle because we don't have to worry about calculating the difference between the canvas height, subtracting off the actual score like we did earlier. So to wrap up, that shows some of the different canvas APIs with regard to rectangles. And you saw two different demonstrations of rendering a really simple bar chart. One is using kind of the standard way and that's the one I showed earlier in the initial demo. And then this shows of some of the different translation and rotation functions that are built-in to the canvas and these are called transforms officially. We'll be seeing more of these as we go throughout the course.
Demo: Drawing Circles
Before we jump in to some demos on using the arc and the arcTo functions, I'm going to take a step back and review two of the specific parameters that the arc function takes because it's important to understand how these work. So I mentioned earlier that the arc function actually takes an X and Y, and that will represent the center point of where the circle starts drawing, takes a radius, and then it also takes a start and end angle, and then something called anti-clockwise which we'll get to in a moment. But I'm going to focus on the start and the end angles. If I want to draw a complete circle, I need to know the angle to start at and to end at of course. And the way it works is a complete circle would have a start angle of zero. We'd go all the way around and 2 times PI represents a complete circle if we put 2 times PI as the end angle. Now, of course, if we wanted something like a 90 degree chunk right here, then I would do zero as the start and 0.5 times PI as the end. And that would draw this chunk here and all these over here would just be left as white. If I want to do a half circle, I'd say zero for the start angle and then 1 times PI for the end. And then, of course, we could do something in between where I draw all the way up to the top right here but then there's just a cutoff right there, that's should all be white and that'd be zero and 1.5 times PI. So now that you've seen that, I'm going to jump into some demos and hopefully make a little more sense as I do some of these different angles and explain how they work. Now that you've seen how the start and the end angles work, let's go ahead and put the Arc function into action. I'll show you how to draw some circles and other types of shapes. So the first thing I'm going to do is let's change our fill style from green which we have up here for the bar chart we did in the previous demo to red. And then I'm going to come in and do the arcs. So we're going to give in an X of 100, let's go down 100 on the Y, the radius of about 30, the smaller the number, the smaller the radius or size of the circle, of course, but it's something like 500 and that would be huge. So we're going to do about 30 and then the start and the end angles. So I'm going to-- say start at zero, and we want to go all the way around. So I'm going to do 2 times math.PI and as I just showed, that'll start on the right side of the circle and go all the way back around to the right. And then we want to go clockwise so for anti-clockwise, I'm going to say false. Now if I run this as is you won't be too impressed because we didn't actually fill it, we told it to do an arc but it's much like the rect function that I demoed earlier in the previous demonstration in the section where if you don't fill it or stroke it, you don't see anything. So we need to fill it. So we simply say context.fill and that will now fill the arc and if we run it, we should now see a red circle here. So there we go. Now we could also come in and instead of doing a fill, we could do a stroke. And right now, the stroke style isn't really set so we could say context.stroke style and let's just say black. And if we do a stroke now, it will just do the outer border of this and you'll know notice it doesn't fill it though. Of course, we could combine those, we could do context.fill and do a stroke on it, and now we'll get our red circle with kind of a black border there. And I'm actually going to change that to white because in the demos coming up, what I'd like to do is basically put data points on the top of each of these bars and have this white kind of blend in here. So that's how you can do with just a basic circle. Now if we want to do maybe a half circle, we could do zero as the starting angle and as I showed, one would be 180 degrees. So if we run this, we should get a half circle. Now if we want to flip that and have it start here and go over, basically we do anti-clockwise and that would go this way. So we'll set this to true and now you'll notice we get the top type shape. And, of course, if I wanted to do something-- let's set this back to false like normal, zero to 0.5 that would give us kind of a 90 degree angle. So let's run that and we'll see that we just have that little slice here that it fills. So that's an example of different types of shapes and how you can use the different start and end angles with the arc, but it's not exactly useful, it just draws some random circles. So what I'm going to do is inside of the loop here, I'd like to go ahead and, at the top of our bars that render, we want to go ahead here and add some circles to represent the middle of the data points on this particular graph. So to do that, we already have our height, we have our fillRect, and all of that good information. I'm going to come down and leave that. And what I'd like to do, though, is we want to come in and we need to set a Y here. I don't want to calculate this again from my arc position so we're going to come in and say Y equals that, and I'm going to put a Y right there. Now, the reason I'm doing that is I'm going to use it again in just a moment here. So let's come on down and I'm going to do a fill style of navy, and then I'm going to go ahead and do my arc. So what I'd like to do is take the currentX, which is going to be the left side of where the rectangle draws, but I want to get the width which is 50, and that'd be the currentX all the way over to 50, and I want to divide that by 2. So we're going to say currentX plus the width divided by 2 and that'll basically position the radius of the circle, or the center point I should say of the circle, right at the middle of each individual bar. I'm going to use Y and then we're going to come in and do our radius. Now, I'm going to do a pretty small one here and we'll do something like 15 and I want a complete circle. So we'll do zero and then we'll want to go all the way around for a circle so we know that we have to do math.PI. And I could do true or false here, it doesn't really matter 'cause it goes all the way around. Now from here, we can go ahead and fill it, and then if I'd like to do a stroke around it, we can set our stroke style. I'm going to do white for this stroke style. And I want the line to be a little bit thicker so I can do that by setting a property called line width. All right, now, I'm ready to go. So I can say stroke and we can go ahead and try this out. So there we go, we're going to go ahead and set the fill from green to navy. Now what's going happen though is it will stay navy if I leave it like this. So I'm going to come in and move the fill style inside of the loop to make sure that the bars stay green so that we basically change our brush every time we loop to green, we fill the rect, then we're going to go ahead and do a fill style of navy, and then we'll do our arc and our stroke here. So let's go ahead and run it and see what we get at this point. And you'll notice it worked but we kind of have this weird line going through which in a way, is kind of cool I guess, but not exactly what I was looking for. What I need to do is when I set my fill style here, I need to tell the context to begin a path. And what that'll do is once we call stroke down here, it's going to basically end the path and then it will stop drawing, and then when it loops back, it won't mix that line in that you saw with the rectangles. So let's run it again. So now we have a nice little bar chart with some data points on it and those maybe a little big but what's nice about this is I can come in and comment this out, and if we just wanted to get some data points, there we have it. Now a little later, we're going to see how we can connect these with line and we'll draw those lines pretty easily. But that'll conclude our example of coming in and using the arc along with the start and the end angles to render circles or I showed how you can render other types of shapes.
Demo: Using arcTo()
You saw how we can draw circles and ellipses with the arc function but the HTML5 canvas also has another function called arcTo which can draw arcs but it's generally used for doing things like rounding corners. So I'm going to show an example of how to do that and kind of how it works. So we're going to draw a rectangle but we're not going to use the simple fillRect to do it. We're actually going use multiple arcTo statements. So, to do that, first thing I'm going to do is I need to begin a path because we're going to be drawing multiple rounded corners and we need to basically connect the paths, connect the dots, if you will, between those. So, I'm going to start off by saying let's move to a specific position. Now you can imagine moving your paintbrush, if you will, up on the canvas and I'm going to move it over to 80 pixels and 50 on the Y. And so, that kind of get us ready to start drawing. Now, from here, we can draw the top right corner. So to do that, we're going to do the arcTo. Now, what I'm going to do is go from 80, 50 over to 210, 50, so we're going to go ahead and put that in. And that will move us over to the right but then I want to go down from 210, 50 down to 210, 70. So we're going to go down a little bit but we're going to round it by 20. So this represents the start X and Y, this represents the end X and Y, and this represents the radius. How, much do we want to round it? If I really want to go big, and I could do 80 for instance, we're going to do 20 here. Now, if we come down at this point and do a context.stroke, this will stroke it with blocks since I have it set, otherwise, and let's go ahead and try to run this and see what we'd get. And you'll see that we now have gone from 80, 20 over to 210 right round in here. But we're going to round between this point and this ending point. And that's why we get this nice little rounding of 20 right here. So, our 210 will be right around here, we're at 210, 50 and here we are at 2010, 70. So, instead we're drawing a straight line over which it would do by the way if I were to just come and input zero as an example, let's go ahead and run that. And you'll see that we just get a straight line, but we want to go down to 70 here, but it's going to round between those points. So, we'd go ahead and put 20 back. All right, so that's our top right, now we need to go down to our bottom right, 'cause we're going to do the same exact thing, arcTo, and we're going to do 210, 200. So we're going to stay on the same X, we're going to jump all the way down from 70 down to 200 now, and we're going to go over to 160, 200 and round by 20. Now, I could change this one up a little bit but this will work. So, let's go ahead and run it. And you'll notice that we now drew from our 70 point down to 200, but we round it with 20, and then over to 160 here, we're at 210. So, we're actually over in here this area. Now, we go ahead and do our bottom left. And for the bottom left, we're going to go over to 60, we want to stay at the same level on the Y that we were, 200. Now, we want to start going up a little bit. So, we're going to do 180, and also round that, save it and run it, and now we should see we kind of have our up arc going. So we kind of connected all of these points. And then finally we can draw up to our 80, 20 area, but we're going need to be a little bit left of that so that we can round it and connect it in. So, we'll do our top left, and we'll do an arcTo. Now, I'm going to start at 60 because that's where we were here to leave off. We're going to go to 50 and then 150 and 20. And what's that going to do is kind of swing out to the left of where we started, and then end 20 pixels over to the right of where we started. We're going to end at 100, but we started at 80. And there we go, so we now have a nice little rounded rectangle-looking type of shape, pretty easy to do, the challenge of course you got to play with these points to get them right, but we started here. We drew over to here, but then set in the second point of this first curve here, round it by 20, then we went from here and drew basically from here to here and rounded that, we drew from here to here, rounded that, and then we of course, basically, drew from here to here and rounded that. So it's one of those things you'll generally had to play with, without an actual drawing tool to use. Now if we wanted to come in and fill this, we could certainly do that. We could add a, for instance, a fill style, let's say navy, and then we'll do a fill. And that will fill in this path that connects all these dots together. Let's go ahead and run that, we'll now get navy and our stroke is not real thick but we could certainly change that in fact just to make it a little more obvious. Let's go ahead and set the stroke style to red and run that. And there we go, we can see we have a nice little red border. We could definitely change the line with if we want it as well but we'll leave it at that. So that's an example of using the arcTo to actually render a rounded rectangle type of shape.
Drawing Lines and Paths
The HTML5 canvas API provides a rich set of functions and properties we can use to draw lines and paths and that's going to be the focus of this section. Now here is a quick survey of the key functions we'll focus on. So we can begin paths, we look at that in a previous section in this module as I showed how to use it with arcTo. We can draw Bezier curves. We can draw quadratic curves, and you'll see there's a little bit of difference between those in how you specify the parameters and to define those. We can close paths, a couple of different ways, we can either call close path or we can stroke a particular path that we might have begun. And then we can move to a particular area on the canvas, specify in the X and Y coordinates, and then draw a line to another area on that canvas. So that's the API functions we're going to look at. So here is a quick run through of some of the key line functions that you might use as you work with the canvas. So beginPath, we've seen before. It simply tells the canvas we're about to start connecting some dots. ClosePath is a way we can close that path explicitly if you'd like. LineTo and moveTo generally go together. MoveTo is where you specify the X and Y coordinate of where to position the brush if you imagine yourself with your hand holding a brush and going up to the canvas. And 00 of course would be the upper left hand corner but we might want to over say 100 on the X and 100 on the Y, and that would be where we're going to start drawing from, then we might want to draw a lineTo, maybe 200 on the X and 100 on the Y, now I'll draw a straight line across. So that's the kind of functionality that we're going to be adding here. Now as you draw lines, there's different properties that you can use to control whether the connecting lines are rounded, how they're kept, how the angle of those look, that's called the miterLimit, and lineWidth, and those types of things. So we'll look at a few of those coming up in some of the demos. Now here's an example of using several of these functions together to ultimately render a triangle. And so you can see we start off as normal by finding the canvas and then getting the 2D context. From there we're going to set our strokeStyle, you can see the red and make the lineWidth a little bit thicker. You're going to set it to 3 in this case. Then we're going to go in and say, all right Canvas, we're going to begin a path. So, this will start the dot to dot tracking if you will. From there, we're going to move our paintbrush, our context over 100 and down 400 on the canvas, and then we're going to draw a lineTo the position that you see down here. So we're going to go down to X 50 over to the left and down 500. From that position, we're going to draw over to 15, 500 and then we're going to draw another line to connect it up which would be 100, 400 which you can see matches where we started in the first place. That actually fill that in, we're going to call stroke and that effectively closes our path, and then we can go in and set the fillStyle to yellow and go ahead and fill it as well if we'd like. And that's how simple it is to draw lines. Now the challenging part of course, is you need to know the X and Y coordinates of all these different lines, but it actually fills those in and kind of connects the dots, if you will. Now in addition to doing that, we can also use some of the more curve oriented type of functions, and we have things like beginPath, closePath again, and we can stroke a particular shape. But we can also do Beziercurves which gives us a couple of control points we have to define. So, a control, X and Y point, another X and Y control point, and then a final point. So you can see that really we have three sets of points that are defined in this case for a Bezier curve. And we can close that path as usual, we can move to the start where that path-- where that kind of paintbrush starts painting at. And then a more simplified version of the Bezier curve is the quadratic curve which has one control point and one ending point. And then we can always stroke or we can even fill those paths if we'd like. Now the same type of things apply, we can apply line caps, and joins, and widths, and those types of things as we're drawing these different shapes onto the canvas. So, here is an example of the quadratic curve and it's a little bit simpler because you define a moveTo point, and they're going to give it one control point down here, and then you'll give it the final point, the X and Y coordinate. And it will automatically round between these points. If you imagine drawing this kind of triangle shape that you see right here, it will basically kind of hug the line but then draw this curve as appropriate based on how far away this is. So if this line over here was way over here, then obviously the curve would kind of come out this way. So, it's a way to draw some different types of shapes and have a lot of control over. Now, if you really need control over, you could do a Bezier curve. Now these are a little more involved because we have different control points. So we'll move to 50, 50, we'll then draw a control point at 5, 400, and we'll have another one at 400, 400, and then we'll end up here at 400, 50 and that would represent our different control points. These two down here and then this one up here represents our X and our Y coordinate. So let's take a look at some demonstrations of drawing simple lines and drawing some different curves using the HTML5 canvas.
Demo: Drawing Lines
In this demonstration, I'm going to show how we can use the moveTo and the lineTo functions combined with some of the properties to draw a triangle shape as I showed in the previous discussion. So to get started, I already have the canvas in our context and we're going to come in and we're going to set the strokeStyle to red, and that will render our border as red, and we're also going to set a lineWidth, and I'm going to make it pretty big, 10. And the reason I'm going to make it big is I want to demonstrate some of the different properties that can be used. Now from here, we need to have the canvas start tracking our dots or our drawing areas, and so we're going to do kind of a dot to dot approach, and so we'll say beginPath, and then we want to draw the actual data points, the X and Y coordinates of where to draw. So we're going to do first off a moveTo, we're going to move to 150, 10 and what's that going to do is automatically grab our brush, if you will, or context and actually move it to 150 over on the X and 10 down on the Y. Now from there, I want to go ahead and do some lines. And we want to draw a triangle so I'm going to do a lineTo from the current position of 150, 10, and were going to go down to 75, 200. So, down this line into the left. All right, if we run this as is, we should see our line coming down now, and there you see it. And I'm a little bit zoomed in right now on the browser 'cause I'm going to demonstrate another feature with properties in just a moment. Now we need the line going across the bottom so we'll do another lineTo and we're going to go 2, 25 on our X over to the right, and keep at the same Y which would be 200. And then we'll connect back up to what we did right here. And if we run that, we should see a nice little triangle. Now you'll notice, it's not quite finished off here, it looks a little bit strange at the top, I'll come back to that in a moment and show you why that is. All right, so that's the first thing. Now as these lines are connecting, there're different properties we can set before we stroke it. So, for instance I could come in and set the lineJoin and the default is miter. And so if I run this again, you're really not going to see any difference here because that was the default. But I can come in and actually set the miterLimit. Let's go ahead and set that, it's normally defaults to 10 but let's go ahead and try 5 first. You probably won't see a lot here but if you watched these corners here, you'll notice it looks pretty much the same. Let's go ahead and go all the way down to one. This is going to in essence it gives a bevel type of effect. And there we go, notice that kind of bevels the end here. The miterLimit controls the angle at which this two will come together and how much of that shows after. And you notice we kind of cut it off whereas 10, it lets these angles go away out. 1 really kind of contracts them back and so that's kind of one of the things that the miterLimit can do. So I'm going to go ahead and just comment that out. Now another thing we could do is we can we set the lineCap, how the lines interact with each other. Now this default it's something called butt although just butt up against each other but I'm going with the round, there's even a square we could do as well. Let's go ahead and do a round and see what we get. And you'll notice at the top it now rounds this, where the lines come together. Now, maybe that's what you want, maybe it isn't. I probably argue that down here, they're not rounded, so maybe we don't want that. But we could even mess with that, with our lineJoin type and we can make that round if we want. But it did at least make the curves at the top come together. And so that's kind of what the round does. Now you can do other values, we can do square, and you'll notice that really kind of looks a little strange. It doesn't really even look square at all but that's what the output would give us. And then the default is butt, and so that's what we had but we still have the gap up here you'll see. To fix that gap, let me go ahead and comment this out, it's really easy. We begin the path and we stroked it but we never told the canvas to actually basically fill in the path completely or close the path. So I'm going to come in and say closePath and now when we run it, you'll see that it's perfect up here, it looks pretty good. And that looks a lot better and, you know, we have the square type of stuff that we want. So that's an example of what closePath is and why you don't have to have it. ClosePath will make it so it fills in those gaps that you saw previously with the different lines. Now just like with rectangles and other shapes, I could also come in and we could set a fillStyle, we'll set it to yellow and we'll go ahead and fill, and let's run that. And there we go, so we have a nice little canvas being rendered, and we could certainly make it a little bit bigger on the top for instance but it works pretty good. In fact-- we-- let's go 20, 20 here down just a little bit. There we go, now you can see the complete top of the triangle it was chopping it off just a slight amount. So, we reviewed that the miterLimit actually controls how the angle of these lines comes together and how much is shown. We can also control the lineCap and the lineJoin, the lineJoin ties into the miterLimit, it defaults to miter. LineCap is the two lines at the top, how did they kind of cap off to each other. And we can do things like round or square, or they just butt up with each other. And then we talked about the importance of closePath so that we actually get the appropriate look and fill up here where the lines meet. And again, if we take that out, it'll work but it doesn't quite look nearly as good, you'll see it kind of chops it off. And it's a little bit difficult to get that nice final look. So closePath plays an important role. So that's an example of using the moveTo and the lineTo functions as well as some of the different properties for drawing lines.
Demo: Simple Line Chart
In the previous section, I showed how we can render data using circles and the arc function built into the HTML5 canvas. And it looks something like this, when we run it, and this plots out some test scores we might have. What I would like to show in this particular demonstration is how can we connect the dots. And connect it with a type of lineChart? So to do that, you'll see I have a startX and a startY variable defined and we're going to be using this to represent the moveTo. And we're going to have a lineTo which is going to represent where we want to go as we space over 50 pixels each time and that's going to represent our currentX we're going to move over to each circle in other words. And we'll start at the center and then we'll draw a line to the next circle in the bunch. So to do this, I need to come in, we need to define our startX and startY as far as the initialization of it. So we have it as zero right now but what I'd like to do is say, if startX equals 0, then let's go ahead and just assign it to an X variable and X, you can see, is just currentX. So startX equals X, and the same thing if startY equals 0, then startY equals the Y. That way we have our moveTo point and that's really what this is all about. This is going to be our moveTo point, then we're going to have our lineTo, we'll do and we'll combine these all together. So we're going to start off as normal by beginning a path. I'm going to set a strokeStyle here. I'm going to do red just to show where these lines are going and how they're not going to overlap with the circles. We can play around with a lineWidth but we're going to go with one for this example. And then we'll go ahead and set our moveTo to the startX and the startY but we're going to do a lineTo the X and the Y. Now once we have that, it's pretty easy, we just do stroke and we can call context closePath. All right, now we need keep our startX position changing the first time it comes through, it's going to be at the same point, the moveTo and the start to will be-- basically be at the same exact location. But then we're going to have the startX and startY remember their locations of where they were so we're going to assign these to the currentX plus, because the arc that's being drawn here, the radius is 10, I'm going to add on 10 pixels to where the line starts. Otherwise, the line will overlap as it renders on-- it will go on top of the previous arc. In fact, let me leave that off and I'll show you why we're going to do that. So let's do startY equals the Y, and so just remember our locations that we are moveTo is always the last location we drew from. So if we run this you'll see it works. So we have our different lines connecting the dots, the line here is actually going behind this, in fact, let me zoom in just a little bit. But you can see as we render a new one, the Z index because it was drown before the arc goes on top. So we need to subtract off or in this case add on the 10 pixels here. So we'll go ahead and say, currentX plus 10 and if we do this, it should fix it and there we go. So now we have a nice little line chart connecting the dots. We're using our arcs for the circles and our moveTo and our lineTo obviously for the individual lines, so let me shrink that back down. So that's an example of how we can actually use the moveTo and the lineTo. Now had we done 2 separate loops, it would've been possible to just connect all the lines at once. For instance when I is zero, we could have moved to the initial position and then from then on as we loop through, if it's greater than zero, we call lineTo, lineTo, lineTo and then fill path or stroke at end of the loop. But in this scenario, I want to go ahead and not only draw the lines out but also render the arcs and that's why we're drawing each line individually, we have a beginPath and a closePath for each of this you'll notice, and that's so that they're individually drawn for each data point. So that's an example of rendering lines to a simple line chart.
Demo: Using bezierCurveTo()
In this demonstration I'm going to show how you can use the bezierCurveTo function to render some Bezier curves. And this is very similar to the quadratic curve function you'll see. Although it provides an extra set of control points that you can define as far as X and Y coordinates go. So just like with the others, the arcTo and the quadratic curveTo, we're going to begin a path. And we're going to move to a start point. I'm going to go to the same one we did with the quadratic curveTo demo. And as a review, here's what I'm after from the demonstration earlier-- the discussion I should say, so we have a moveTo, we're going to define a control point here, another control point here, and this is where it differs from the quadratic curve because that only has one control point. And then we'll define our end point as you can see here. So let's come on in and do that and we'll simply come in and say, let's do a Bezier curveTo and we'll go 50, 400 that's our first control point. Then we're going to move over to 400, 400, that's our second control point, and then finally we'll move back up to 400, 50 And if we go ahead and instruct this, we should see a nice kind of even line here and there we go. Now if we want to fill this in, we could come in and do a lineTo this position here the X, Y coordinate over to the initial 50, 50 position and that would then fill that in. So we'll do a lineTo 50, 50 and we'll go ahead and stroke that, and there we go, and then of course if we want to fill it, we could easily do that by saying fill. Now we didn't define a fillStyle so of course it's going to default to black and there we go. So that's an example of how we could fairly easily, once you know those coordinates anyway, to find some different types of curves that would be really difficult to do which is basic lineTo and moveTo. So as we move these control points, things will change a bit. So let's go ahead and mess with this first control point here. And let's say we wanted to move it over to 100 and run it now. And you're going see it's going to move the curve over. You can see how it kind of slightly changed it instead of being equal, jumps on over and of course if we move over a little more severe to say, 300 close to the second control point here, then we'll get another gradual curve going over that way. So it provides a little bit more flexibility versus the arcTo or the quadratic curveTo if you need that extra control point. Now if you just need rounded corners then you could definitely go with the arcTo or the quadratic curveTo because they're pretty much similar as far as what you define in the parameter set. Whereas this one defines the 2 control parameters and the final ending point parameter. So that's an example of how we can use the Bezier curveTo function.
Demo: Using quadraticCurveTo()
Several different techniques can be used to render paths with the HTML5 canvas. Up to this point, I've shown the arcTo function which can render some types of paths. And in this demonstration, I'm going to show the quadratic curveTo function and show how it can be used with the control point and an end point. So to get started, I already have the context, a strokeStyle and a lineWidth set and I'm going to come in and begin a path just like we normally would. And I'm going to moveTo a start area. So we're going to go to 50, 50 on this one. Now as a quick refresher from the previous discussion, what we're going to do is moveTo a position, define a control point down here at 50, 500. And then have an end point of 500, 50 and what the HTML5 canvas API behind the scenes will do is automatically draw a curve that kind of hugs these 2 lines that you see here. And then gradually rounds this out nicely. And if I move the line out this way, then the curve will be much broader. So to do that, we're going to come in and do a quadraticCurveTo call. And what I'm going to do is move to those same data points 50, 500 and 500, 50 and then we're going to stroke it. So if we run this, we should get a nice little line here and there go. And now if we wanted this to be a little more gradual on the swish side of things on the curve, then we could certainly move this out. Right now or width is 800, so let's try to go up maybe 700. Run this and you can see that we now have a nice little swish type of thing going on if we wanted that type of a shape in our canvas. So that's an example of quadratic curve and kind of a simple application. Now I have in my clipboard a function that also uses quadraticCurveTo as well, I'm going to paste that in. And this particular function also uses the moveTo and the lineTo that we looked at previously, and what it does is draw some lines then draws a curve. Draws a line and a curve and we're going to get a rounded rectangle out of this. So now we're going to have a reusable function anytime we want to define one, where we can pass on the context. The X and Y coordinates, where to start. The width and the height, and the radius of the curves, and we're going to use those to define where the control points go and the end points. So if we come down in here, we'll go ahead and call roundedRect. We'll give it our context 200 by 200 and a radius of 20 on the curves. So if we run this, we'll get a nice rounded rectangle as you'll see here and now I have a reusable function I can call to do this type of thing and I showed another way to do this with the arcTo as well. So you can kind of take your pick on which direction you want to go. The arcTo is actually a little bit less code but this one is already done and you could certainly take this and extend it if you'd like. So that's an example of how we can use the quadraticCurveTo to define a control point and then an end point and how the canvas will take whatever we started out, go to that control point and then a nicely gradually round out the curve along it to end up over here.
Drawing Text
In addition to rendering rectangles, ellipses, lines, and paths, the HTML5 canvas API also supports rendering text directly to the canvas. So in this session, we're going to talk about how do we render text. Now fortunately the API is very simple, in fact there's a very small subset of functions out of all of them available that you'll actually use for text and those are shown here. We have fillText, measureText, and strokeText. Now these particular functions are very, very simple to work with. The fillText takes the text you'd like to render. You can set the X and Y position of where that text should go as well as a maxWidth of that. MeasureText is used to get things such as the overall width of what the text will be. That way, you can figure out if it will fit into a certain area or not. And then strokeText, instead of filling in the text, it'll actually just put a border around the text and you can see that it actually takes the exact same parameters, the text, the coordinates and the max width that you'd like it to have. Now, we can also set things like the font, we can set the text line, text base line, and this is for alignment left and right, and up and down, and things like that. And we can also go in of course set the fillStyle and the strokeStyle depending if we call fillText or strokeText. So let's take a look at a demonstration of how we can render text to a canvas.
Demo: Filling, Stroking, and MeasuringText
Rendering text to a canvas is a fairly straightforward process, there're only 3 main functions we use, those include measureText, fillText, and strokeText. So in this demonstration, I'm going to show how we can use those functions. So to get started, I'm going to define some text and we'll just do something simple like "Hello World," and then I need to set what is the fontSize, and the font I want to use, and we do that off of the context through the font property, and we'll say 40 point with Arial. Now I can do strokeText or fillText if I want to write it out to the screen. Let's go ahead and do a strokeText first. We'll give it the text and let's say we want to start at 50, 50. And if we run that, you should see "Hello world" is written out, and you can see it did stroke it as opposed to filling it. Now if we wanted to come in and fill it as well, we can do a fillText and we give it the same parameters here. If we run it, it's just going to look all black you can see. You can see a little bit of a fill there or a stroke combine didn't look too good. Now to see the difference, let's go ahead and set the strokeStyle. Let's maybe change that to navy and let's set the fillStyle to yellow. Now if we run this, you're going to see it's going to work but it won't look super gray and I'll explain why. So you can see, it did work, let me zoom into that a little bit, but it's not real crisp you can see. And that's because the fill went on top of the strokeText that we did. Let's go ahead and move this up, and by moving this up, it will make it a lot cleaner-looking because it's going to do the stroke after the fill was done. And so if we go back to kind of normal view there, it looks a lot better, a lot crisper. So that's an example of how to get started using the fillText and the strokeText. Let's go ahead and add the measureText function into the mix. So I'm going to come on back to our code and let's comment this out. And I'm going to paste in a little sample code that I already have prepared here. It's going to do a very simple loop and write out the text but we're going to use measureText down here so I'll get to that in just a moment. So we're going to start the fontSize at 10, we're going to loop from 5 to 25 incrementing by 5 each time. And ultimately, that's going to take our fontSize and increase it by 5 each time. And so what we'll do is we're going to write out some dynamic text based on the fontSize. We're then going to set the fontSize dynamically based on this fontSize variable. Then we're going to measure the width of the text, we're going to use the measureText function which takes the text to measure which includes also the fontSize that we've used. And basically, gives us back the pixels of how wide that font is. Now we're going to use that in our fillText down here so you can see we're going to jump it down by Y and then we'll increment our fontSize by 5. So measureText is a great way if you need to find where the text should go such as how do I want to center it on the screen. Well, to do that, you need to know how wide it is and this will let you get that. So if we run this, you'll see, it will simply spit out some text here. Now, you'll notice that the text up here if we were to flip this on this side here, that's the kind of difference between the two. This one if you flipped it on the side, that will go all the way up to the top, and that's the width of that and it just kind of bumps the text down based upon how wide it is. And it's bumping it down from the top that's why there's this gap here initially so each of these bumps down a little bit further because it's a little bit wider of course. Now later in the course, I'm going to show you how we can use measureText in a little more useful way to determine how to center some text on a chart then I'm going to show you how to build from scratch. So we'll be taking a closer look at measureText as we move along in the other modules in this course.
Demo: Using Canvas Transforms with Text
As you work with text on a canvas, there are maybe times when you need to transform that text in some type of different way. Maybe you need to rotate it, or scale it, or just move it somewhere on the X, Y coordinate system. So in this demonstration, I'm going to show how we can work with transformations and text. So you can see that I already have a font defined 30 point, Arial and we're writing out some text, regular text to the X, Y coordinate. Let's go ahead and run this and you'll see that we just see Regular Text. Now what if we wanted to move this text and flip it on the side though. So flip it basically so it's vertical. Very useful in situations like charting for example, how do we do that? Well, fortunately the canvas has some built-in transform functions built-in such as translate which moves along the X, Y coordinate system. And we also have the rotate which can allow us to flip text in some type of different direction based on degrees. So to get started, I'm going to define a rotated text string here. And what we're going to do is go ahead and fill this. We're going to take the rotated text, I'm going to put it at 0, 0 right now. And we if we run it, it will show up in the upper left hand corner and you can't even really see it because of where it's rendering it right now. But we have rotated text. So what's going to happen now is I want to rotate it on its side. So to do that, we can come up above and tell the context that I would like to rotate the next thing that's going to happen. And we're going to rotate using the same types of concepts I described in a previous section on the arcs and circles. We're going to rotate it 0.5, but I want a negative 0.5 so just to keep it real clear, we'll do 0.5 times math.PI. Now .5 normally, zeros on the right, .5 is on the very bottom of a circle, negative 0.5 is going to rotate at back up to the tops or basically going up 90 degrees. All right, now if we do this, the problem is I can run it but everything is off the screen at this point, it's over here somewhere. And so what I need to do is actually tell the canvas that I want to translate this over and down a certain amount and then rotate it. We'll do that by calling a translate function which is another type of a transform. We're going to go over 100 pixels and down 300 pixels in this particular demonstration. Let's go ahead and run that now and you'll notice we now get the rotated text. Now, the challenge with this is getting the translate right of course because for instance if I were just to come down maybe 100. Let's run that, and you'll notice where it currently is showing, so you kind of have to play with this a little bit to get it positioned right on the X, Y coordinate system but that's what the translate is for. So let's go ahead and do that. Now let's say that we want to go in and we want to add in a bottom set a text which is just regular text below this one but I want it to be horizontal not vertical. So I'm going to grab our same type of text but I'm going to cut and paste in a little bit of code here. And we're going to take the width of whatever we rotated. So our text, in this case rotated text, which takes into account the font of course. We're going to measure that, get the width, and then I'm going to fill some text which I'm going to use the same thing as I did up here, regular text put it at 100, same as this but I want the Y to be below where this one shows. So I'm going to take the width of that because keep in mind it's now flipped, so the width represents the height of that text and I'm going to add 120. Now, if we run this, it's not going to be quite what I wanted, you'll notice that it's still rotated, I wanted it right down here though, it's not what happened. Now the reason for this is once we switch the rotate and do the translate and all of that, the context of our canvas stays in that mode. So everything I draw from now on will be rotated and that's not what I want. I want to do a temporary rotate and translate, and then switch back to normal and then draw this. And the way we can do that is by saving the current state of the canvas, the current context. We'll do the translate and the rotate, we'll go ahead and fill it, that will draw our vertical text and then we'll restore the canvas with the context back to what it was before we did the rotate. So you can almost think of this as taking a snapshot of where things are right here then will go ahead and translate and rotate, draw out our text then we're going to restore back to the original snapshot. Now, this would be just like normal and we'll be back to horizontal text. So let's go ahead and save this and run it and there we go. So you notice that we wrote out what we had to start which is pretty simple. We rotate it. We save though before we did that, so it saves the state of the context before we rotate. Do the rotate and then translate then we restore back to where we were and that way, it will be back to normal as we start to draw. Now, if I wanted everything to stay rotated by this kind of 90 degrees, then we could certainly do that, of course, and just not do the save and the restore. But these are really, really useful little tricks to know as you work with the canvas especially if you're building a costume chart or anything where the text won't necessarily be vertical. And this applies to not just text by the way, we can use the save, the translate, the rotate and others with other types of shapes as well. So that's an example of working with transforms and text.
Drawing Images
The canvas API provides a robust set of functions for rendering rectangles, ellipses, paths and even text, but there may be times when you want to embeds some images that you have on hand into your canvas. So we're going to talk about how to do that in this section. And here are the functions I'm going to cover. We're going to talk about how we can create wallpaper type patterns with createPattern. We're going to look at drawImage which does exactly what it says. It draws an image into the canvas, and we'll even talk about how can you take a canvas and convert that canvas into an image. So here are the different functions and the parameters that they take. CreatePattern takes the actual image as you want to use that as the pattern and then a pattern enumeration. And you'll see in a moment, we can repeat on the X and Y axis. We can draw an image by giving the image to draw and this will be a DOM object representing an image. We can give at the X and Y coordinates of where to start drawing and then the width and the height and this overloaded. You can also pass some additional parameters when you want to crop images. Well talk about that a little bit. And then finally, toDataURL can be used to convert a canvas into an image. Now, the createPattern has this pattern parameter as the second parameter you can pass in. And here're the values that are allowed. So if you'd like to do a wallpaper type of pattern, you want to repeat an image on the X-axis, you can say, repeat-x, or if you want to go vertically, you can repeat-y, you can do both or you can do no-repeat. And I'll show an example of how to use a few of these as we jump into the demonstration. So in the demo that follows, I'm going to walk through the three functions that you just saw here, show how that can be used, and demonstrate how different parameters can also be passed into these functions.
Demo: Using Image Functions
To add images unto our canvas, we can use the drawImage function and we can also convert a canvas into an image using the toDataURL functions. We're going to take a look at both of those. Now, I'm also going to show another technique that can be used with images called createPattern as well to show how we can make a background type of wallpaper pattern if we wanted on our particular canvas. So in the code I already have here, you'll note that I am creating two images. Here's the first one and here's the second one. And what we're doing is creating a standard, DOM image object. I'm saying that when it loads, we'd like to call a drawImage function which we're going to create in just a moment and we're going to pass it the actual image that loaded, that way, we know it's ready and download it. And then we're also going to set the source. So, what will happen is we create the image, we assign the callback when it's done and then we set the source, drawImage will then be called. Let's go ahead down here and I'm going to add a drawImage and it's going to take the image that we want to render to the canvas. And we're going to do some pretty specific things with this. I have just some simple variables here to represent on the canvas the, destination X and Y and the width and the height that we'd like to render. Now, I have in the project a very simple HTML5 logo then I'm going to render here and you'll see it in action in just a second. And to draw it, we're going to use the more simple set of parameters for drawImage here. We're going to pass the image, the destination X and Y and then the width and height, and that's it. And that will do is put the image 10 over 20 down and then it will be 212 by 212 and the image we're going to load here is an images folder called HTML5.png. So we go ahead and run this and you'll notice that we see it and looks pretty good. So that's the first thing on using drawImage. And now, we could also come in and do drawImage and actually control the size and area of the source image that we grab and I'm going to paste in a little bit of code for this one because it's very, very similar of what I just showed, just a few more parameters. Let's tap this over. All right, so what we're we going to do here is the image itself, I don't want to grab the whole image we're going to say. I only want to grab part of that image and render it on the canvas. So I'm going to define a source X and Y and I want to start in the upper left-hand corner of the image, 00. Then I'm going to go 512, which for this image happens to be the full width and-- but we're only going to grab 110 whereas the image itself is actually 512 by 512 if we're going to grab the first 110 pixels down. Now, I'm going to change where I render it as well. So the X, the Y, the width and the height of destination on the canvas are very similar to what I did up here, we're just going to change those numbers a bit. Now, moving down to drawImage, you'll note that there's a lot more parameters here than the first time I used it. In this particular case, we're not just going to say where to write the image, that's the destination, X, Y, width, and height. We're going to say I would like to grab the X and Y-coordinates and width and height from the source image. So I don't want to grab the whole image, just part of it. I'm going to crop it in essence and then I'll say where to render those. So, these parameters are identical to what you saw up here. They'll control where this image goes on the canvas. Let's go ahead and save that and run it and we should see two images now. And you'll notice that I only grabbed the very top portion of this HTML image that you see here and then we render it to the canvas. Now, this can be useful on a variety of situations if, for instance, we're making a game and we're working with sprite sheets they're called where you have Mario for instance and different poses running, then we can grab different sections of that main image and then render that particular section on to our canvas using this technique. Now, if you just need to grab the whole image, you'll certainly want to just go with the more simple set of parameters here but this is kind of nice if you want to come down to this option and pass some of the more involved parameters and crop out parts of the actual image. Now, I'm going to ahead and come back up here. We're going to comment out and drawImage and I'm going to comment in and draw wallpaper. Now, the wallpaper that I have is very simple, if we come in to images here. Here's the HTML5. Here's the wallpaper. So what I'd like to do is treat it like wallpaper and put it into rectangle but I want to repeat it either on the X-axis, the Y-axis or maybe both and we'll do both in this particular demonstration. So I'm going to add a new function here called drawWallpaper. And it's going to take the image just like before and this is pretty simple. What we need to do is call the createPattern function off of our context. And I'm going to give it the image which is that wallpaper image and then the second parameter is how do I want to repeat it? Now, you can use repeat-x, repeat-y or just repeat in all directions if you'd like. I'm going to use repeat in this particular demonstration. So let's go ahead and add in repeat right here. And that will take care of repeating that, not only in the X but also on the Y-axis. Now, if just want to do the X or the Y, I would do repeat-X or Y, we'll do all. There's also an option to do no repeat if you don't want to repeat it, but normally, when you create in a pattern, you probably want to repeat it. So coming on down now, we're going to go ahead and set a fill style but instead of doing a fill style like we've done up to this point with, for instance, a color, we're actually going to give it our pattern and now, we're going to render that into a rectangle. So, I'm going to call the rect function we've talked about earlier. We're going to put and add an X, Y, width, and height location here and then we're going to call fill. So this part here is very, very similar to what we've done before earlier in this module and then this course but this time, instead of just painting a color or filling a color into the rectangle, were going to ahead and grab that image and then repeat it, so it will repeat to automatically fill this width and this height here. Let's go ahead and save that and run it and then there we go. Now, had I done something like no-repeat? You'll notice that's what the original image actually looks like but because I did a just repeat of the X and the Y, it actually fills the entire rectangle area as you see here. It automatically kind of stitches that together, if you will. Now, the final thing I'm going to show is how we can actually grab the data from a canvas and show it as an image and you'll note that there's a button down here called showCanvasImage and it's going to call this function I'm going to create called showCanvasAsImage and what I'm going to do here is use a function called toDataURL. So I'm going take our canvas which currently is stored as a global variable, you'll see it right here and we're going to say canvas toDataURL and then I'm going to do a window.open and show the actual data. So we're going to show the dataURL and just say canvas as image as the title of it. We're going to put a width and a height. So let's do a width of say, let's go about 300 and a height of maybe 300. I think that will fit it okay. And let's save it and run it and you're going to see this isn't going to work out so well unfortunately. So I'd like to save this so I'm going to try to pop it up. You'll notice I don't get anything. Well, if I go into the-- in this case, Chrome Developer Tools, you'll see I have an error and it says DOM Excetion 18. Now, normally, the reason you'll get this is if one of the images that you've load into the canvas comes from a different domain, then you're not going to build and covert your canvas into an image. Let's just do the cross domain restrictions. Or in this example, you'll note that I'm running it right off the C drive as a file and that won't work either. Now, fortunately, if this was on a web server, this would work okay. So I'm going to go ahead and open this file in Visual Studio since this will add a little web server for me and what I can do now is right-click, say View in Browser and this will automatically allow me to show a pop up because all my images are local. First off, I'm not calling a cross domain and also, as I try to convert this into an image this canvas here, because I'm on a web server now, it will work. So to show canvas as image, we get a nice pop up and there we go. That's my image that was actually created right there. Now, what it does is it actually makes a special URL here up at the top and the URL-- oh, it doesn't show the whole thing here, actually has a base 64 encoded string of data which modern browsers know how to convert that into images and then display them and that's what's happening here. Now we can do the same thing, if I were to come back into here, let's comment out the wall paper and comment back in the drawImage with the HTML5 image. Once this loads, you'll see that we can actually render this image and we'll now draw it and there we go. We actually drew it and this is a separate window. This is truly now an image, I can actually save it if I want as an image and do something with it. So that's an example of some of the different image functions that are available with the HTML5 canvas.
Drawing Video
One of the more creative things you can do with the HTML5 canvas is embed video and this provides for some very interesting scenarios in fact, I showed one of those in module 1 as I demonstrated some of the sites out there using the canvas. Now, fortunately, if you want to work with video, you already know what to do. In fact the function used is the drawImage function that we just covered in the previous section. Now, the difference is as the video plays from an HTML5 video tag, we need to capture frame by frame those different videos and then draw an image and I'll show you how we do that in the demonstration but it's very, very simple to do actually. We're going to use the same exact parameters that I showed earlier so we'll be passing a video though in this case instead of an actual image tag. We'll pass the X and Y-coordinates of the destination on the canvas where we want that video to show and then finally, we'll give it the width and the height of how big the video should be. And I really think this opens up for some very creative and kind of cool possibilities because we can have a video for instance playing in the background and overlay different texts and shapes even images onto that providing some nice visual effects if that was needed for your given application. So, the best way to see this is to actually just look at a demo so let me go ahead and jump in to a demo and show you how we can embed video into the HTML5 canvas.
Demo: Syncing Video with a Canvas
Adding video to a canvas is fairly straightforward because we only have to call the canvas' drawImage function to do it and then combine that with a timer. And what we'll be doing is as the video plays, we want to grab different frames on a timer basis and then render those frames into the canvas. So it's actually pretty easy to do. So you'll note that I have a video tag down here already. It is set to autoplay and it loads an MP4 file that has a promo clip from a movie called Real Steel. And if I run this now, you'll see that the video loads up and plays and what I'd like to do is as the frames of the video play we want to go ahead and load those down here into what will be our canvas area and then kind of sink it up. Now, you'll notice that the movie itself kind of starts with the boring stuff, so I'm also going to skip the current time forward about 10 seconds so that we jump right into the movie and then the canvas will start rendering. Now, as we pause this, we also want to pause down here and if we get to the end, we want to stop at down here as well. So I'm going to do all of that. So the first thing we're going to do is grab our video DOM element and we're going to do a standard getElementById and you'll see that the ID of this is video, so let's go ahead and put that up. And once we have the video, we need to handle when it plays, when it pauses and when it ends. So, to do that, I'm going to add an eventListener for the play and then we need a callback function and we need to do that three times so let me just cut and paste that down. And this one will be for pause and this will be for end it. Now, when it pauses or ends, I want to stop a timer that you're going to see I'm going to start into play, the timers down here so I'm just going to call stopTimer, I already have that in place, and we'll do that in both spots and that will basically clear the timer so that the canvas stops rendering anything because at that point, there wouldn't be anything to render, of course. Now to play, the first thing I'm going to do is jump the video forward to skip the boring stuff, so I'm going to jump it forward, let's say 10 seconds here and then we want to start a timer. So up top, you'll notice that I have at timerID and I'm going to assign that to window setInterval which will start the timer going and we're going to fire it every 30 milliseconds. Once the current time is going and set, we're going to say timerID equals our setInterval. This takes a call back function for when the timer fires, what do you want to do. So we'll end our function here first and we'll say every 30 milliseconds, this is when it should fire. Now, from here, it's very simple especially if you watched the image section of this particular module because we can just call it context drawImage and we can give it the video and that's the DOM element we want to render and that's going to basically take a snapshot of that video as the timer fires. We're going to move it down just a little bit on the canvas as far as X, Y and then for width, we're going to do 270 and 125. All right, so that takes care of handling our play, our pause, and our ended. And there's others you could certainly work with here potentially but this will handle all the main things we would need. When the play fires, this is the most important one, we'll jump the video forward, we'll start a timer that fires every 30 milliseconds and that will just keep running and take snapshots of this video and render them down to our canvas using drawImage. Let's go ahead and save it and try it out. All right, so we'll wait for this to load up and it should jump forward 10 seconds once it starts running here. And there we go. You'll notice that here's our video up top. This is actually the canvas, it looks like it's video but in reality, it's actually taking screen shots, if you will, of the video and rendering frame by frame but you can say they're staying right in sync here as it plays and renders to the canvas. This is really nice. Now, if I come up and pause it, when you pause it, well, it's going here though. There we go, we'll pause it and you'll notice that this automatically pauses down here and then if we play it again, it's actually going to jump back to 10 seconds because that's where I told it to go but it will start it back up. So it's not that hard you can see to render video to a canvas. That's all we have to do. Really, the hardest part is just getting the timer started and stops. From there, it's just a matter of calling drawImage.
Summary
In this module, we took a look at some of the key functions available in the HTML5 canvas API and we've focused on drawing rectangles, ellipses, and circles and things of that nature. Rendering arcs for rounded corners and even took a look at how we can draw different shapes with lines, Bezier curves and quadratic curves. I also walked through how we can render text onto a canvas, how we can even translate and transform and rotate that type of text to make it more from a horizontal view to vertical, very useful for things like charting when you have like a Y-axis you want to show. I showed how we can render images and how we can even convert a canvas into an image if we'd like and finally, how we could render video. And then along the way, I showed several properties we can use to do things such as control the fill color, the stroke color and even line width and things of that nature. So this is a good module to go through when you need to get started with the canvas because a lot of what we covered you'll be using as you render different shapes, text, videos, or images. But there's even more you can do. So in the next module, we're going to go a little bit deeper and talk about some of the other canvas API functions that are available.
Manipulating Pixels
Introduction
In this module, we're going to drop down to the pixel level of the HTML5 canvas and learn how we can interact with pixels directly. Up to this point you've seen how we can render shapes and lines and images and even video. But what if you want to dynamically generate graphics and render pixels on the fly or manipulate a picture in some way that may be on the canvas, work with gradients, or even animate pixels and the different items that are in your canvas. So here's the overall agenda of this module. We're going to start off by talking about how to work with linear and radial gradients. From there we'll move into transforms and we'll even learn a little matrix algebra along the way and learn how we can scale and rotate and translate items on a canvas. We'll talk about direct pixel access. And this is very useful if you want to get little more advanced and iterate through pixels on a canvas and maybe grayscale an image, for instance. And then finally we'll talk about how do we animate pixels on the canvas, and we'll talk about a loop we can write using either a timer or a built-in browser feature for some of the more modern browsers out there that allow us on a time basis update the pixels on the canvas. So let's go ahead and jump into gradients.
Rendering Gradients
Gradients are commonly found in applications ranging from the Web to the desktop. And the HTML5 canvas fully supports rendering gradients directly. So in this section we're going to talk about how that works and the API functions that you need to know to do it. The three main functions that we're going to talk about are shown here. We'll talk about create radial gradient, create linear gradient, and how we can add colors into our gradients using add color stop. That's all there is to use. And it's very, very simple to get started rendering gradients as you'll see. Here's an example of the different functions and the parameters that they take. So add color stop, you can see, takes the position and the color that you want to position in the gradients. So you can do everything from a simple gradient going from something simple like white to gray or maybe a rainbow gradient for whatever reason. And you have a lot of different colors. Regardless of which route you choose, you're going to use add color stop to add those colors into either a linear or radial gradient. Now, if you're going to do a lineal gradient, this is typically something that goes in a square or rectangle. You're going to define a x1 and y1 coordinate. And that will be the starting point of the gradient. And then you'll define a x2 and a y2 coordinate. And that will be the ending point of the gradient. So for example, if I wanted to go diagonal, I might start at 0, 0 and go down to, say, 200, 200 and that might do a diagonal. And that's how the gradient would actually render. Whereas, if I start at the center point, at the top of a rectangle, and go down to the center point at the bottom, obviously that would be a top down type of gradient. You can also render radial gradients. And the x1 y1 defines the starting point of the main starter gradient you'll go with and the radius -- how big is that first area going to be -- over to an x2 y2 and that radius. So this is pretty useful if you want to render, for instance, a little shine on a circle or a ball where you have maybe a blue color, let's say, for the ball, but in the upper left-hand corner you want a little white type of shine which almost looks like the light is shining on that. And that's how we do that is with radial gradients. And I'll so you that in some of the demonstrations coming up. Once you've created a gradient, you need to assign it to either the fill style or the stroke style. And then that will be rendered as you fill a rectangle or draw and stroke an ellipse or whatever it may be that you're doing on the canvas. The way that we actually render the gradients and the direction they go is shown is here. As I mentioned earlier, with a linear gradient, you have a x1 and a y1 and then x2 and y2. So if we start that up in the upper left-hand corner and then have the x2 y2 in the lower corner, then we'd get this type of diagonal gradient. You can see we're kind of going from white to a bluish color. Whereas, if I were to start the x in the middle the square or rectangle, but have the y be at the very top, then we'll start at the very top and go down, in this case, to the center point of the bottom and we'll have a top down gradient. Of course, I can position these any way I'd like. If I'd like the gradient to go from the lower left up to the right, we can do that as well by simply changing the x1 and y1 and the x2 y2 coordinates when we call create linear gradient. And I'll show an example of this as we move into the samples. When it comes to radial gradients, you can also define the coordinates here as well. So here's a example of kind of that shine I was talking about. The outer gradient or the main gradient here is a blue. But then it's going to transition -- and you'll notice it's a circular transition, though -- into this white color. So the outer one might have a position of 200, 140, which may be the circle here -- center point the circle, I should say -- and it has a radius of 100, so it's pretty big. Whereas, the ending point the gradient, you can see, is going to be white and ends at 180, 80, which is obviously over a little on the left and way up on the y axis. And it has a radius of 8. And so it's a lot smaller. And by controlling the size of these different radius aspects and the size of those including the x and y coordinates, you can do some pretty interesting effects. And I'll show a demonstration of that coming up in the demos. So let's go ahead and jump into a demo first of using the linear gradients and then I'll also show a demo of using the radial gradients.
Demo: Creating Linear Gradients
If you're working with shapes in the canvas that need some linear gradients, then we can use the create linear gradient function. And that's what I'm going to demonstrate here. So to start off, I've already grabbed the canvas in the context. I've identified the x and y center points by taking the width and height of the canvas and dividing by 2. And then I have some built-in functions -- draw outer gradient, draw inner gradient -- and then we're going to just render some text. Now right now, the gradient functions you see here don't actually render a gradient. One has a fill style of black, the other one has kind of a light gray. So let's go ahead and run it and you'll see that's what shows up. And we get our black with our light gray inside of it and there's our text on top. But what I'd like to do is the draw outer gradient, I'd like to have kind of a white to gray and on the draw inner gradient, I want more of a white to kind of a bluish type color. So let's go ahead and add that in. So the first thing I'm going to do is we're going to take this out, and I'm going to make a variable called gradient. So I'm going to go ahead and just type that there. And we'll make our gradient variable here. And we're going to do that by saying context.create linear gradient. Now, I needed to give it the x1 and y1 coordinate of where to start the gradient. So I'm going to take that center x. -- I already have from on top. And for the y we're only going to go down about 20. Then I'm going to grab the center x again, and we're going to go down to around 230 on this one. Now, if we ran it at this point, it wouldn't be too impressive because we don't have any colors in the gradient, of course. So what I'm going to do is say gradient. And we're going to add a color stop. And at the initial position, I want this one to be a white. And for the second one, we want this to be kind of a light gray. And that will take care of it. So let's go ahead and run it and we should now see the black is replaced and we can see kind of a white down to a gray. And because we started at the center point of the x, that centered it and went straight down. And that's why the gradient goes this direction. Of course, I could go any direction I want. If I put the coordinates over here at the start and the end over here, then we'd have a gradient going that way, of course. Okay. So let's move down to our inner gradient. And really it's the same exact thing for this one. So we'll go ahead and paste that in. But I'm going to change this up just a little bit. We're going to change this to about 200 since it doesn't go down as far. And other than that, I'm going to change the color from our light gray to kind of a bluish color. Now, we need to update our fill style to use the gradient. So we simply assign it like we did above. And if we run it, we should now have two linear gradients displayed and there were go. So now we have our white to kind of gray. And then we have our white to kind of a light blue going on. Now, we could certainly add more colors into the mix if, for instance, I wanted to come into here. So now about half way in the gradient we should see a slightly darker blue. And there we go. Now, it doesn't look too great with that text, of course, but we could go in and change the text to white and it would look a little better. But that is an example of how we can go from a white to a darker blue, down to a lighter blue at the bottom. And you can do some pretty interesting effects with that if you want it. But that's an example of how we can work with linear gradients and how easy it is to add those in so we can get this type of an effect in our canvas applications.
Demo: Creating Radial Gradients
Creating radial gradients is very similar to the process of creating linear gradients. The main difference is in addition to finding where the gradient starts and x and y coordinates, we also have to say the starting point radius and the ending point radius. Other than that, it's pretty much identical. So right now I have a very similar application as I showed earlier in the lineal gradient demo, and I've identified the context. I have the center x and center y. And I have a new variable here called radius, which we're going to be using to render two arcs. And if I run the app now, you'll see that this is a third of the overall canvas size, so the canvas goes out to about here. And we have this circle with a circle on top of it. And it looks fine. But it could certainly be made better if we add a little bit of a gradient into it. So what we're going to do is come in. And right now I have kind of a light gray for the outer circle. That's that bottom, bigger circle. And we're going to do a very similar process to what I showed earlier with the linear gradient. So we're going to create a new gradient. And I'm going to take the context, and we're going to create radial gradient. And for the positions I'm going to take the center x, and I'm going to take the center y. I'm going to divide that, though, to change it up just a little bit by 1.2, and the radius. So we're going to grab this kind of third radius of the overall width of the canvas and we're going to use that. Now, that's going to be our starting x and y coordinate and the size of our radius for this. So right now the canvas is 300, so obviously the radial, a third of that for the width for that is going to be 100. So for the x and y of the ending point, what I'm going to do here is we're going to say we'd like 100 by 50. And I'm going to do radius divided by 2. So we're going to take about half of the 100 to about 50 for the ending point to make it more focused. Now, if I run this as is, it's not going to be very impressive again, because we have to add in some color stops. So if we're going to add in a color stop, go ahead and add this at the zero. And for this one we're going to go to white. So we'll go to the 1. And the range of these gradient stops is always between 0 and 1. Basically 0 percent and 100 percent. We're going to do white. And that's it. So we've defined our x and y coordinate of where to start. The radius is going to be about 100 for this one. Then our end is going to go from 100 to 50. So it's actually going to go up towards the left. And the radius is going to be half of the overall size up here, which will be about 50 pixels. So if we run this, we should see some kind of white shine up in the corner here and you can see that. And that gives us our nice little gradient to work with. And then it kind of fades in over here, you can see, into that ccc which is kind of a darker gray. That's our initial one. Now, I'd like to do the same thing, though, with the blue to kind of make it fit in and kind of have a little bit of a shine to it. So I'm going to come into here. And we'll just cut and paste this. We're going to change this to gradient and let's paste in what we have. And then I'm going to tweak this a little bit. All right. So the first thing that I want the to do is as we're working with this, I'm going to definitely change up the positions for this little bit. So we're going to go in this one, because the circle is little bit smaller. Instead of 150, I'm going to do 70 and 50. And I want is smaller radius. So I'm going to go down to 4 -- divided 4. So 25 percent of 300 basically. Now, for the coloration of this, we're going to do a kind of light blue type of look. And we want to go down to white. So we're going to go ahead and leave that. And that's pretty much it. We've assigned the gradient to our fill style and we're ready to go. So let's go ahead and run it. And there we go. So we have a nice kind of blue that blends in nicely with our gray. And you can see that if the sun were shining, it's kind of shining down in this direction, and it gives us that nice little lifted effect for our canvas object. So it could be a button, or you'll see later we're going to use it in a different way. So that's an example of how you can use create radial gradient function in a canvas application.
Using Transforms
As you're working with canvas, there may be times when you have a shape or a text or something like that that you want to rotate or scale or skew. And to do that we can use the HTML5 canvas transform functions. So in this section that's what we're going to talk about is how can we transform things. It's a very good skill to know about as you work with the canvas because it comes up quite a bit actually. Now, here's a set of the functions we're going to talk about. Restore is used in conjunction with save to basically save the state of the canvas, then do some type of transform, then restore the canvas back to what it was before you did that transform. We'll talk about that more coming up. The more obvious ones here are we can rotate something by a specific angle; we can scale something up bigger or scale it down smaller; and we can use two different functions here, set transform and transform. And I'll explain the difference as we move along. But these are used for more complex transformations where you want to combine a bunch of features all in one transform function call. And then finally, translate is used to actually move a particular object somewhere on the canvas. You can translate the x and the y coordinate. They could just as easily call it the move transform, if you will, because that's what it does. It moves things around. Here's a look at the different parameters that are passed into these functions. You'll see that save and restore don't take anything at all. You can just call them directly. Rotate takes the angle that you would like to rotate. And you can give it a negative angle, as well, if you'd like. Scale takes the scale of the x and the scale of the y and how much bigger or smaller you want to make that. And then finally, translate also takes in x and y and then moves something in the canvas. So for instance, if you want to translate by, say, 100 by 100, you would go over 100 and down 100. Then you could, for instance, do a rotation or something. You'll often use translate as you're doing things like rotations, because otherwise what will happen is the text or whatever it is you're rotating may go missing off the screen. And that's because after the rotation, it rotates off. And you need to translate it over, back on to the screen. And we'll talk more about that as we go through some of the demonstrations coming up. Now, behind the scenes, matrices are actually used and specifically matrix algebra, to calculate the ending x and y positions or coordinates as you perform a transform on an object. So for example, if you do a rotation, well behind the scenes, it's actually skewing and scaling the item. The rotate function that I just talked about a little bit earlier is actually just a simple API you can use. But behind the scenes, what's really going on is there's a matrix that's set up. Now this is one way to represent the matrix. And this is what you'll see in the canvas documentation and in other places. But the 0, the 0, and the 1 at the bottom, which are always fixed constants, every now and then you might see them up here as the column. So you see 0, 0, 1. But this is the normal way that you'll come across it. Regardless of which way it is, ultimately you can achieve the same result. Now, this is a simple matrix. And you can see that it's a 3 by 3 matrix. So we have 3 across and we have 3 down. Now, what this does is it allows us to supply some values to do some things such as let's scale the x or scale the y. Now, you'll see where those are used in just a moment. But in a nutshell, what goes on behind the scenes when you're calling the canvas transforms is it's actually performing some matrix algebra. So let me show you an example of how this works. Over here on the left we have the ultimate goal we're after. We'd like to get the x, the y, and then the 1 always stays constant on this bottom row here. But over here we have a scale x of 1 and that's the standard. That's normal. We have 0 on the skew of y, and that's kind of the default. But the translate x is going to be minus 100. So we're going to move the x position over to the left by 100. We have down here the skew x is 0. So no skew at all. Skew's kind of a fake 3-D and 1 represents our scale y. So, again, that's our default. And then our translation for the y is -- we're going to move it back up because we're going minus 200, so back past 0, actually. Now to actually put this altogether and make something useful and calculate the x and the y, what you have to do is take a single column with three rows in it. Because when you do matrix algebra and where you're going to multiply, the ending 3 -- if we go rows and columns we have three columns -- so the starting, which is 3 for our rows must match that. So if you have a 3 by 3, then you must have a 3 by something in order to do the multiplication of the matrix algebra. Now, I'm not going to go too deep into it, but I'm going to show you how the behind the scenes code works as far as what the canvas does to make these calculations. So what it does is really simple. You take the x and multiply it times the first one. That gives us x. You take the x and multiply it times the second one. That gets a 0, so we're still at x. Then you simply add the remaining number. So because it's negative, we subtract, of course. So we have x minus 100. Same thing for the y. Y times 0 is 0. Y times 1 is just y. That gives us y. Then we're going to have minus 200. And then this bottom one, if you do 1 times 0, 1 times 0, we have 0. And 1 times 1 is 1. So that's why you always have a 1 on that bottom one. So behind the scenes what's going on when we use some of these functions such as at rotate or the scale or the transform or the set transform that I'm going to talk about next, it's actually doing matrix algebra and multiplying these matrices to figure out the end x and y position of where things get moved. So by combining scale and skew along with translate, you can rotate in scale and skew and do all kinds of things. The HTML5 canvas actually uses the matrix algebra with two specific functions called set transform and transform. Now, the difference between these two is that set transform, if you already have transforms in place, it clears those and resets to what's called the identity matrix or the normal way to look at an object as it would be rendered by default. Transform takes any existing transforms and works with it from there. So it doesn't wipe out what was already there. It kind of builds upon it, if you will. So set transform kind of wipes things out. Transform works with what you have. Now, they both take the exact same parameters. And you'll notice that these parameters actually match up with the different matrix algebra, columns and rows, that I just showed right back here. So if we go back, we'll see that for our matrix algebra, we had the scale x, skew x. That's the A and the B or 1 and the 2 parameters, if you will. And then we have skew y, scale y. And then we have our tx and ty. And that's our translate. So if we go back, you'll notice we have scale x skew x; skew y scale y; and then translate x and translate y. These actually match up to the rows and columns I just showed you with matrix algebra. And behind the scenes as you change this values, it's actually going to use those to perform that simple multiplication I showed you between two matrices and then given the ultimate x and y coordinates of the object that you're working with. So the best way to learn these is to actually see a demonstration and I have a demonstration coming up. So let's go ahead and up into the demos, and I'll show you how we can use some of these different transform functions to rotate scale and do other things to things on a canvas.
Demo: Getting Started with Transform Functions
Up to this point in the course we've seen a couple basic examples of using transforms. But in this demonstration I'm going to talk about them a little more fully and demonstrates what you can do. So to get started, I'm going to come in and we're going to render some text. And although we played with text earlier, I'm going to show some different things that we can apply to the text and how that affects other things. We're going to talk about things like save, translate, rotate, scale, and restore and the effects of those different functions. So to the start off, I'm going to come in and define a font for our text. We're going to do 30 point arial. And then from there, I'm going to call save. And what that's going to do is save the current state of the actual canvas. So the rotation of it, the scale of it, everything, as is. It's almost like taking a snapshot of it. We're then going to translate to 200 by 350. We're going to rotate. We're going to go negative .5, so we're going to rotate the text up on its side. So we're going to do negative .5 times math.pi to get the appropriate angle. And then we're also going to scale the text. 1.5 on the width and 4 on the height. Now, I'm going to comment that out just so we can see that without that first, and then we'll come back and add that. From here we can go ahead and render the text. So let's just call this rotated text. And we'll call to your standard field text and give it that. Now, you'll notice that I'm going to write this as 0, 0. Now, the reason for that is it I'm actually translating to 200 on the x and 350 on the y. So I want to do 0, 0 here. I'm not actually writing on the standard canvas coordinate; I'm writing according to this translate that I did, and that's why I did the 0, 0 there. All right, now what I'm going to do illustrate a point here is just render a simple rectangle a little bit over to the right. Let's do 100 on that. And let's run this and see what we get at this point. So you notice that we have our rotated text and we have this rectangle over here to the right. Well, I'm going to comment out the save and the restore. And let's see what happens here. Now, keep in mind we're translating 200 by 350 and we're rotating negative .5 times math.pi. Basically, we're going over 90 degrees up to the left, in this case, of the text. So let's run this one more time and see happens here. You'll notice that everything got rotated, including the actual rectangle which is actually now going off the screen here. And it's not quite right, you can see. It doesn't fit right. It doesn't fit in with the scene at all, because we've actually done this translate and now I'm giving it different positions. Now, we could come in and let's say 0, 0 for the xy. And now you can see it fits in kind of like it should, or little better anyway, because it's being rotated based on the translation and the call to the rotate function. Now, let's go ahead and go back to what it was. We're going to leave that. And I'm going to put back in the context save and the context restore. And let's go ahead and run that. Now notice the rectangle stays exactly where it should have been. In fact, if I were to comment all this out, and run it, we just get the rectangle, and that's what it would do by default. This really illustrates the importance of the save. That's what we have here. Because what it does is it save a snapshot of the current state of the canvas. Then we're going to go ahead and do the translation and the rotation. I'm going to go ahead and put the scale back in on this and then we're going to write out the text. Now, if we didn't do the save with the restore though then even the rectangle you saw would also be rotated which is not what I want here. So the save and restore are very, very important. Any time you want to do some type of a transformation to one thing, then restore the canvas back to its original state so that everything doesn't get rotated from then on in the code. Let's go ahead and run this as is. And you should also see now that the text is scaled. Now, it doesn't look too great because of the font size and things. It would obviously be easier to make that bigger just by changing the font size. But that demonstrates how we can actually scale our text dynamically. So that's a simple example of the main transform functions that are available and how you can use them and actually the text example is pretty real life if you're going to be the doing things like charts, because you might have text that needs to show kind of vertically. So in the demos that follow, I'm going to show some other examples of how we can use these transform functions.
Demo: Using transform() and setTransform()
Using the scale, rotate, and translate functions is fairly straightforward. There's not a lot of parameters you have to pass and not a lot of code to write in general. The transform and set transform functions, on the other hand, are a little trickier to understand. Behind the scenes, I mentioned earlier that they actually use matrix algebra. And so to demonstrate how the different parameters work and the effects they have on objects in a canvas when you call transform or set transform, I have a sample app here that kind of shows these different parameters in action. So you can see that I have the first two parameters that would be passed. That's the scale x and the skew x. The next two consist of the skew y and scale y. And then the final two are the translate x and the translate y. And so you'll notice if I start playing with these, the scale's pretty obvious. We can skew or scale. And you can see as I do that it affects that. The skew, you can see what it does on the y. And then here's the one when I do the x of it. And behind the scenes, when you do a translate, a rotate, or a scale, it's actually doing this type of math -- or matrix algebra math -- and using these transform or set transform functions -- depending on what's going on. So if I reset this back to 0, this is called the identity matrix, where you have a 1, a 1, and a 1 down here. And so when you have a 1 on the diagonals, that's kind of the normal way things are rendered. But as soon as I start to tweak this, now we're obviously doing some matrix type of math and it's figuring out the xy coordinates of how to actually render this, combined with all these factors. So there's an example of kind of mix and matching these different types of things. Now, we can also move it over. This is the translate x which moves the x direction. And we can move the y that moves the y. If I do it while it's in normal mode, you'll notice it moves it as expected. We can go up or we can go down. So that's what actually happens behind the scenes as you work with the transform or set transform. Now, the code to actually do this is pretty simple. I go grab the values from those different text boxes at the top of the screen. And after clearing the canvas, I call set transform and that wipes out any of the transforms currently in place and applies these new ones that I have right here. So I grab these scale x skew x and skew y and skew y and different translate x and y coordinates. Then I fill the rectangle and restore the canvas to back where it was. That way if we had any other shapes, it wouldn't mess them up. So that's all that's going on, is that one little line code, as we change those difference values, that manipulates our rectangle. Now, that's not that fun of an example though. Let me pull up another one here. This example is one where I run it, it actually renders and bunch of squares in a neat little circle here. And you can see that we also supply some dynamic colors. If I hit refresh, you'll see the colors change there. Now, what's going on with this is I'm using the sign and cosine functions in JavaScript to grab the sine and cosine of math.pi divided by 20, first off. I'm then doing a translate to canvas.width divide by 1.5 and the height divided by 5. And that will reposition us on the canvas. That translates the x and y coordinates again. And then from here, we're going to loop basically until 40. And this part here just dynamically creates the red, green, and blue components that are going to be rendered for the boxes. We then fill a rectangle and we transform it. Now the transform takes the cosine sign, the negative sign, and cosine. And this is a well-known algorithm to do exactly what I'm showing right here. It's something that literally on Wikipeida find this type of algorithm for rendering this type of graphic. And we're just using the transform function to do it. Now, as we loop through this, you'll note that we're not calling set transform every time. We're starting from where we last transformed and then adjusting it to these different parameters. Otherwise, if we call set transform -- and let's run that -- you'll notice it kind of goes off the screen. It's definitely not at all close to what we had here, because it's clearing the transform everything single time it renders. And that's why we're only seeing two squares here. And the others are just off the screen. So that's an example of another way that we can use the transform, which is very, very little code, to actually do some pretty cool things with the HTML5 canvas.
Accessing Pixels
One of the more powerful features available in the HTML5 canvas is the ability to access pixels directly. Now, this is a feature that you may not need in every canvas application that you write. There's many applications where simply rendering shapes or images or even video is all you need to do and you don't really care about getting into pixels. However, other types of applications may need direct pixel access. A simple example would be you might load photos into a canvas and allow user to, for instance, make it grayscale or you want to allow them to, say, change the sharpness of that particular focus of photo. Well, that type of operation is going to involve direct pixel access. And, fortunately, we can do that. There's three functions that you'll use if you want to directly access pixels, and those are shown here. If you want to create pixels from scratch -- basically create them out of thin air -- then you can use create image data. If you'd like to get existing pixels that are on a canvas that you already have rendered, you can call, get image data, and that returns a collection -- an array -- of some data you can get to that contains the rows and columns representing every pixel in that canvas. And then once you're done, you might want to send those pixels somewhere such as back to the canvas, so you can see the changes or to another canvas. And you can use put image data to do that type of operation. Now, why would you want to manipulate pixels directly? Well, as I mentioned earlier, there's actually several reasons. One is maybe you want to dynamically generate a background that displays on your canvas. Something like shown here, for instance. Well, you could do that using direct Pixel manipulation. If it's photography or something related to that, you might want to change hue or saturation or contrast or even convert to grayscale. You might want to sharpen some of the colors. Really any time you'd like to change pixel levels, then you can go in and use the HTML5 canvas APIs that I mentioned earlier to actually do that. Now, one thing to keep in mind that's really important if you do want to manipulate pixels and go to that level. If you load any images -- which, of course, are pixels themselves -- and they're not from the same domain as the domain that served up your webpage that contains the canvas, then you're going to run into some security problems there. And the reason for that is we don't want to be able to manipulate pixels from another domain. There's actually just a lot of issues that open up as far as security goes and cross-domain type of attacks. So make sure that the image, if you are using an image, is served up from the same host that served up the original webpage that contains the canvas. That's really important and something you might fight if you're not aware of that particular limitation. Now, here's a rundown of the actual functions and the parameters that the functions take. You can see that create image data, if you want to create pixels from scratch, you can give it a width and a height of how many pixels you want. As far as how many columns, how many rows. You can also give it -- if you have existing data you can pass at that existing data and then work with it. If you want to get data from an existing canvas, you can call get image data off of our context and then give it the x and y coordinates of where to start on the canvas and the width and the height you'd like to grab. And then, finally once you're done manipulating the pixels, you might want to put them somewhere. So we have a put image data. And that takes the actual data that you want to work with and that would be the pixels and the array of pixels that you're working with. And then you can pass several parameters after that. The designation x and y of where those pixels goes on the canvas would be the next two parameters that you see right here. And then if you only want to a grab a portion of the data that you're going to write to the canvas, for instance, maybe you just want the first 100 pixels over and 100 pixels down, and within the to ignore everything else, then you can give it the x and the y -- that's the starting coordinates -- and the height and the width here. And that will only grab that portion of the data. Now, before I show you how to actually manipulate pixels, let's look at how pixels are organized and structured. So every pixel is composed of four main components. A red, a green, a blue, and an alpha. So here's an example of one pixel. And you can see that it has those four components inside of it. So we control the color of that pixel by controlling the red, the green, the blue, and then the alpha, allows for more transparency, if you want it to be more see through or not. So the red, the green, and the blue, and the alpha go from 0 to 255. 0 if you had a red of 0, a green of 0, and a blue of 0. That would be black. And if they were all 255, that would be white. And then, of course you can mix and match in between. And that's actually how every pixel that's rendered to the canvas is showing a different color. It's a combination of the red, the green, and the blue. And then if it's really transparent, it's because the alpha is more towards 0. The alpha itself is actually a 0 to 1 type of ratio when it comes to opacity. But when it actually comes to the component of a pixel, it's 0 to 255. In this case, we have 3 pixels going across. And then we have 2 pixels tall, you can see, for a total of 6 pixels. And so if we were going in and, for instance, grayscale all of these -- which I'll show a demonstration of that coming up -- then we're going to have to loop through every single position in here and change the red, the green, and the blue to something more along lines of a white, a black, or a gray type of color, of course. And we'd have to loop through, starting here. And this would be 0 and we go all the way 11. And then we move to the next row, and that's 12, and all the way to 23 over here. And that would allow us direct pixel access. Now, the way it works in that nutshell is we can use the create image data or the get image data to either create or get some pixels. So let's take a look at those. So here's an example of create image data. We're going to create some pixels basically out of the blue. We're going to do 200 on the width and 200 on the height. Now, what I'm going to do is iterate through each of these. And we're going to do that by simply grabbing the pixel data that's returned from create image data. And we're going to grab the total length of those pixels. And the reason we're going to increment by 4 is because, as I just showed, we have the red, the green, the blue, and the alpha. And so every pixel is actually four components. So to grab the red, we're going to grab pixel data 0. To grab the green, we'll grab 1, 2, and then 3. So you can see, we have 0, 1, 2, 3; or 4 total components of this particular pixel. Now, from here, if I were to change the pixel data i to a different 0 to 255 range, then we can actually control the color of that pixel. And by doing that across multiple pixels, we can do some pretty interesting types of things. Now I'll show a demonstration of how to do some interesting things, like grayscale and even dynamically generating interesting background images using the canvas, just out the blue, using this type of logic. Now, once we're done working with those pixels, we'll probably want to put them back to a canvas. In this case, we're going to grab the current context and say let's put the image data, pixel data, assuming I manipulating the RGBA components of each pixel. Let's say for instance I grayscaled them, then I would write this data back to the source canvas where I originally got them, starting at 0, 0 on the coordinates. So if the canvas itself was 200 by 200, I made new pixels 200 by 200. We would completely overlay the existing pixels with the new pixels that we iterated through here. So let's take a look at how we can do this programically with JavaScript using the HTML5 canvas.
Demo: Creating Pixels Dynamically
Let's take a look at how we can use create image data function to generate graphics on the fly with the HTML5 canvas. So you can see I already have a canvas defined and a little bit of code up top here. So once we've found the context, I'm going to call generate image and generate image simply grabs the height and width. Now what I'd like to do from here is generate a background for this canvas. It's going to be a pretty interesting type of shape based on some algorithms you can use. You can certainly tweak what I'm going to show you to come up with different results. I'm going to go ahead and first add a variable called pixel data. Now this is going to represent our blank pixels that we want to write some colors to and dynamically generate on the fly. And to do that, we're going to call create image data. And we're going to give it the width and the height from the canvas width and the canvas height, which is 600 and 600. Now, once we have the pixel data, it's empty at this point. So we're going to be writing to these pixels and specifically to the red, green, blue and alpha components of each pixel. So the first thing I'm going to do is calculate the center point. So we're going to take the width divided by 2 for the x and then I'm going to do the same thing for the y. We'll take the height divided 2. And I also need to track the position of each component in the pixel. And so I need to know the 0 through 3 is going to be the first pixel. And then 4, 5, 6, and 7 is going to be the next pixel. And so on and so forth. So I'm going to add a pixel position. Really it's component position because it's component within the pixel. But we're going to set that to 0. All right. Now, we have a 600 and 600 as far as how wide is it and how tall is it. So 600 on the height, 600 on the width. I'm going to loop through the rows and the columns. So the first row is going to have 600 pixels across. And we're going to do that 600 times down because our height is 600, of course. So to do that we're going to add in a simple loop. And we're going to start at 0 and go while y is less than, our pixel data.height. That's going to represent looping through the different rows in our empty pixels right now. Then inside of that we need to loop through the columns. Let me go ahead and put a comment here. We're going to do rows first. And we're going to do x less than pixel data.width, increment it by 1. And this will represent looping through our columns. Okay. So that will loop through each row. We'll start at 0, we'll go to the 0 position. And then once we're at that first pixel, we want to get to the RGBA components and work with it. But I need to know how far offset it is, because that's going to change how I render things. So I'm going to calculate an x offset here by taking the x we're looping through -- which is the pixel in the column -- and subtracting off the x center. That will tell me how far off the center point it is. We're going to do the same thing for a y offset. And that will get my x and y offsets. Now from there I'm going to use that to calculate a delta here. So we're going to take the absolute value of the x offset. And we're going to add in the absolute value of the y offset. And, again, we're doing that to figure out how far we're off from the center of this canvas. And then finally I'm going to calculate a tangent here. I'm going to take that delta divided by 10. All right. So that is just a little algorithm that calculates how far is a given pixel from the center point. And we're going to be using that to generate some colors and things coming up, this t value. So is the rest of this I am going to paste in. It's a fair amount of code that is used to just generate the colors. So you can see here -- let me space this over real quick -- and you can see that we have the red, the green, and the blue component of each pixel that we're going to work with. And what we're going to do is dynamically calculate a value. Now, these are values, as you see here that it's not something I just pulled of thin air as far as the values you see here that are hard coded for the constants. These are things that I played with. The image you're going to see that's generated is kind of bluish looking. And so I just played with these different values to get what I wanted. So we're going to take this tangent value times 255. So this will be a decimal. I'm going to grab a percentage, in essence, of 255, so that we have a value between 0, which would be black, and white which is 255 for the red. And then the green component we're going to take 125 plus that t times 80. And then finally we do the same thing with the blue with different values. Now, what I want to do and need to do down here is the pixel data. We can access each pixel by getting to the data, and then the component of the pixel is an array. And so I'm going to say for the pixel, get into the component. And we want to get to -- and the first time this runs we'll have a 0, because that's what it was set to up here. And we're going to take the math.max. And what I'm doing is basically grabbing the red, grab the min of 255 -- or r -- and then same thing for g and b down here. And then do a math.max of 0 or this value over here. And it will dynamically grab one of those values on the fly. Now for the alpha, I kind of played with this one. I'm just taking a random value that will be generated between 0 and 1 and multiply that times 1000 to see how opaque it is. And what that will do, you'll see, is actually generate kind of a dotted look -- or speckled look -- I should say, probably. So let me comment that out first. And we're going to leave that. Now what I need to do, once we're done looping through the rows and the components and updating the components of pixels, is we need to put that back to our canvas. So I'm going to call the put image data, and we're going to give it the pixels we want to work with which is our pixel data. I'm going to write that to the 0, 0 position of the canvas. And that will basically take these pixels I created up here. We loop through and fill each the components values, RGB and A once I cut back to this. And then we're going to dump that data on the canvas. And that's what the input image data does. So let me go ahead and save and run this. Okay. Now that's what we get out of the box. And you'll notice, number one, it definitely doesn't look very blue or anything. So let me though my alpha in first. And then we'll see if I have any issues in there. Okay. So you can see it changed actually a whole bunch by putting the alpha value. Because without that in there, you can see, we kind of get this weird-looking pattern in here. Very interesting. Whereas when I put that in, we get what I intended. And we get this kind of rotated rectangle look or diamond type of look, I guess, that spawns off from the center point. And then the further away it gets from the center, you'll see the bigger the sideways row and squares get that you see here. So it's a pretty interesting effect that's 100 percent dynamic. Now, if we didn't want the speckle look we could come in, do something like this. And now notice we have a pretty sharp kind of blue there because we're not doing any of the pixels and making them either transparent or opaque. Right now everything is very visible. And, of course, if I did 0, this won't be very impressive at all. We're basically turning all the pixels off and that's what we get there. So that's one of settings you can come in and play around with. Now the same thing goes for whether you're using tangents or I can even mess around and do cosine here. And what this will do is just generate different types of items that you'll see. And it's pretty interesting what you can do. Let's try a sign. And that's actually pretty close it looks like. Then we'll go back to the tangent. And so, what you can do is go find some of these algorithms out there to generate different types of shapes. If I wanted to draw swirls, I could do that. There's a lot of cool things you can actually draw dynamically. So that's an example of how we can dynamically render pixels to a canvas using the combination of create image data and put image data.
Demo: Grayscale Pixels
Having direct access to pixels really opens up some cool opportunities when it comes to manipulating those pixels and working with things such as photos. So in this demonstration I'm going to show how we can load up an image and actually grayscale it with just a very minimal amount of JavaScript code. So I already have a little bit of code in place here to fire up a new image object. We're going to handle the on load, which is going to draw that image on to the canvas and position it. And then I'm going to call this grayscale function. Now, currently, you can see that it doesn't do anything. But we'll come back to that. Now, the image that I'm going to load is just HTML5 logo. So if we run this as is, you'll see that we get a color version of the logo that shows up. Now, to grayscale this, I need to loop through each of the pixel components. So I need to get into the red, the green, and the blue and manipulate those. And ultimately tweak it a little bit. And it's not a lot of code to do this. So when the grayscale is called, I'm going to actually come in and access our pixel data. Now, we can get existing data on the canvas because this would be after the image drawn. Then we'll call it grayscale here. And we can get that image data by simply calling get image data. I'm going to say, grab the whole thing for the canvas. We're going to start at the xy coordinates of the upper left-hand corner, get the entire width and the entire height that we have defined here. Now, I'm going to go ahead and add height and width up here. And so that will get us to the raw pixels. Now what I can do is get to the data of each of those pixels, and that gets us to the individual four components, red, green, blue, and alpha. So I'm going to shorten that up a little, and we're just going to call that data by saying pixel data.data. That will get me to the individual components of each pixel. Now I'm going to go ahead and loop through each one of those. So we're going to say data.length for when to stop. And I'm going to increment by four because we know that we have the red, green, blue, and alpha values. So we're going to loop through each of those, then increment by four. And do the next for the following pixel and so on and so forth. Now from here, I'm just going to cut and paste in a little bit of code I have because it's just some sort manual typing. And this will actually get a gray version of whatever data we have. So data i is going to represent as we look through the red. We're going to multiple that times .3. Data i plus 1 is going to get us the red green. So we'll have the green. And here's the blue. And you can see that we're just multiplying some decimals here. Now, you could certainly change the number that you multiply and get some other interesting effects, but we're just going to do a simple grayscale example here. Okay. Now that I have what a gray pixel looks like, I actually need to go and assign that to the red, the green, and the blue values for the actual pixel that we're working with. So to do that, we're going to go back into the i and assign that to the gray. And that's going to be our red component of the pixel. We'll do data i plus 1. And that's going to be our red and green. And then we'll do data i plus 2. And that will be our blue. And that's it. That's all we have to do is iterate through all the individual parts of a pixel to get the red, green, blue. We're going to convert whatever is there into a gray version of it and then reassign it back to the red, the green, and the blue for that one pixel. Now, of course, we need to take that pixel data and dump it back on the canvas. And we're going to call put image data to do that. Okay. Now an interesting thing you'll see here is when I run this -- let's go ahead and try it out. We'll probably see nothing. Well, as far as the grayscale, I should say. So if I come in and look at the errors, you'll notice that we get this security exception. And the reason is I'm not running this on an actual web server. I'm running directly off the hard drive. And because the image is viewed as being a different folder, it just doesn't work. It doesn't like it. Now, this also applies in the Web world. If you have an image from a different domain, it's not going to work. You'll be shut off, and you'll get this happen dom exception here. Let me go back to that. And you'll see this dom exception 18. And it gives you a pretty good error. Unable to get image data from canvas because the canvas has been tainted by crossed origin data. Now, the first time you see this, if you run it off the hard drive, you'll probably be a little baffled. And that's because you need to run this off of an actual Web server for it to load appropriately -- in this particular example, because I have it in this images folder. So I'm going to go over to Visual Studio and run it. And we should now get a grayscale version. And there you go. So you can see it works. It's in the same domain. But now, because it's loaded from an actual web server, it loads it appropriately, and we don't get that cross domain issue. So going back to the code, that's how easy it is to actually come in and grayscale a photograph or whatever it is that you want to show on the canvas. You can do some pretty interesting things with this, you can see. So that's a wrap on this particular demo on how to manipulate pixels.
Animation Fundamentals
In this section, we're going to look at how we can animate the pixels on our canvas. Now, animation is not intrinsically build into the canvas out the box, unfortunately. However, using the timer or some other tricks, we can actually animate items on a canvas. So let's go ahead and jump in, and I'll show you how it works. Now, as mentioned, although the canvas doesn't natively support animations, there are some techniques that we can use to perform animations. And, in fact, the canvas, when it comes to animations, actually performs very, very well. And that's because we're actually rendering pixels directly to the canvas. Now, one technique that can used is we can use the standard window.set interval. And that would be a timer. And we can have it fire every certain number of milliseconds, so it fires, and we clear the canvas, and then render and clear and render and clear. And we'll talk about kind of a game loop that you have to write and how that works in just a moment. Now, more modern browsers are actually a little more efficient. When you do the interval, it will fire the timer whether the browser's ready to do that or not. So it's possible that you could actually drop some frames here and there. Well, with request animation frame, this is a technique that you can use to actually call into an object that's available, and the browser will give you a frame that you can then animate with. And so if the browser's really available and there's not a lot going on, you can do super high frames per second. If, however, it's bogged down, it will try to optimize that as much as possible so that when you render, you don't drop to, say, three frames per second, and things don't look so good. So the steps that you're going to follow regardless of whatever technique you use are shown here. First off, we need to either have a timer that fires or we request a frame from the browser. We're going to then update the positions. We'll just have a simple update routine that will say on our x maybe we want to move that over by 5 every time it fires. And then we're going to clear the canvas. That's going to clear all pixels on the canvas. Or you'll see that we can actually clear a portion of the canvas if we want. And then we're going to draw to the canvas. Now, if the background and everything changes, then, yes, we're going to have to delete or clear all pixels, re-render all pixels, and do that, say, 30 frames per second or 30 times per second. And that's the routine that you use to animate. Now, if you've ever worked with games in the past, this will sound pretty familiar, because this is what we've done. You have a game loop. Well, this is very, very similar to a game loop where you're going to repeat this process over and over. Now, here's an example of the standard timer way to do it. And this works in pretty much any browser that supports the canvas. We use the window object to get to the set interval function. And set interval takes the function to call once the timer fires and the number of milliseconds in which we want to fire that. So maybe if we do 30, that would be 30 milliseconds. So every 30 milliseconds, it would actually fire, and this function inside would be invoked. Then it's up to us to update the positions, clear the canvas, and then re-render everything and then draw it back to the canvas. The more modern browsers out there are now building in the capability to request an animation frame rather than using a timer that you really don't have any control over and where frames per second could drop down pretty bad, instead of letting the browser determine the ultimate frame rate. Well, these modern browsers now have this request animation frame that you can call in to and it takes a callback function. And in this example, when the animate's called, we're going to update our positions, clear the canvas, draw it, and then we're going to say, all right, give me a new frame. Once that frame is available to animate into, we'll call animate again, and we'll repeat this process over and over and over. Now, the difference here between the previous one where we set an interval is that the browser is actually determining the optimal frames per second based on other processing that's going on within the browser. So it's definitely more efficient and the way to go. Now, the problem with this approach is that not every browser supports request animation frame. In fact, a lot of the browsers out there will use vendor prefixes on the front of this. So let's take a look at how we can kind of remedy that and put a shim into place. Here's an example of a custom object we're creating called request anim frame. Now, you'll note that that's a little bit different than request animation frame. And what this does is act the same as what I just showed you. You pass in a function with a callback. And what's it's going to do is if the browser itself supports request animation frame, it will return that object and you can use it. If not, it's going to check if it's a Webkit browser. Now, that would be Safari or Chrome. And if it's one of those, it will return the Webkit request animation frame object, and we can use that. It's going to check, if that's not there, are we on Firefox. That would can the moz prefix. Are we on Opera, or are we on a Microsoft browser that has an MS request animation frame. Now, if none of those are found, if it's a slightly older browser that still supports the canvas but doesn't support this request animation frame, then we're actually going to resort to our standard window.set timeout. Now, not set interval. What this will do is fire once, invoke the callback. And this will do 60 per one second. So 60 frames a second. It basically provides a nice fallback for us where, if these other objects aren't available, we'll just simply invoke this one time. Then it gets called again, we'll invoke it. And we'll just keep invoking it over and over and over. So that's an example of how we can actually trigger animations. So the best way to learn animations is to actually see some demos. So let me go ahead and jump into some demos, and I'll show you how we can animate pixels on a canvas.
Demo: Getting Started with Animation
You can add animations into a canvas by either starting a timer or requesting an animation frame. And I'm going to show both techniques in this demonstration. So to get started, you'll notice I have a window unload where I find the canvas. And I store that up here because we're going to be using the context in several different places. I also have a radius defined. That's because we're going to animate an arc or a circle. Starting position y and position x, a speed and a direction. We're going to be using those coming up. Now, moving down, you'll see that I have an empty animate function. We have an update function, and we have a draw function. So the process is going to be we're going to kick off the animate that we'll call update and draw. Update is going to update the position of the arc that is going to be rendered in the draw that you see here. You'll notice that when draw is called, we also are going to clear the canvas. We're going to do that using clearRect function. Once the canvas ask a cleared, we're going to go ahead and set the fill style and do a pretty standard arc rendering. And we're going to render a complete circle, as you can see here. Now, the update that you see here is going to be used to change the direction in which the arc that I'm going to show is animated. So we're going to determine if we're moving to the right or to the left by a little direction -- dir -- available. And if the position x is less than the canvas with minus the radius of the circle, then we're going to go ahead and change things up. So if it's less than the canvas width, we want to keep moving to the right. Otherwise, we want to start moving to the left. And that's why we're going to do a minus 1. If, on the other hand, the direction is less than 0 -- so we're moving left already. As long as it's greater than 0, including the radius, then we want to go ahead and keep moving left. Otherwise, we're going to switch it to move right. Now, the reason I'm calculating this little variable here -- the dir -- is simply to multiply that by a speed, which you saw up top is set to 8 right now. And this will control how fast our little ball bounces back and forth between the walls of the canvas. So that's what's going to go on. Now, what I'm going to do is come on in and when the window loads, I'm going to call animate. That's going to kick things off. Now animate is going to call in to the update to update the position first, then it's going to call draw. Then I need to actually re-render over and over and over and do the same thing. Now, what I'm going to do, though, is we need a timer here to start off, and then I'll show how we can request an animation frame. So I don't just want to call animate once. I want to call it on a time basis. So to do that, I'm going to call window.set interval. We'll give it a function for our callback. And that's going to call in to our animate. All right. So what that will do is kick off a timer and that set interval fires every 60 milliseconds. It's going to call animate. We're going to update. We're going to draw. And then these are already filled in, and do what I already walked through. So let's go ahead and run this and see what we get at this point. And you'll see that we get a little ball moving from left to right. And we can change the speed and how it runs by setting that, for instance, to 10. And that should speed it up just a little bit. Then we can go really fast, of course, if I set it to, say, 50. Then we'll come in and it will be quite a bit faster here. You can see we move it back and forth. Pretty basic. So although this is a very fundamental type of animation, this is the general concept that you'll follow when you want to work with animations. What I just did works; however, the modern browsers add a new feature called request animation frame that I discussed in the previous section. And rather than setting the interval, I'm going to go ahead and use this request animation frame. So I'm just going to come right up top here and paste in some code. And this is giving me a little shim. It's going to add a little functionality. If the browser supports request animation frame, we're going to return it. Otherwise, it's going to look for a Webkit version of that. Mozilla, Opera, Microsoft. And if that doesn't work, we are going to fall back to a standard set timeout, which makes a single call. Now, what I'm going to do is, we're going to kickoff animate, because we still need to call that. But animate, once it does the initial render, is then going to turn around and say, all right, let's request an anim -- I'm going to take this guy right here -- frame. And then the callback it will call is animate. And that's how we're going to work it. We're going to go in and say request an animation frame. And the callback that should be called once the frame is available to animate on, is the animate. So we're basically going call this over and over and over. Now, if we go ahead and run as is, it really won't see much of a difference. However, the browser itself is now controlling when an animation frame is an available. So the frames per second should be a lot better in general than if we just used a standard window.set interval. Now, this isn't a feature that every browser supports quite yet. And that's why we have this shim in place. Because if it doesn't, we'll fall back to the set timeout which will call once, then animate gets called again at a set timeout over and over and over. And just keep calling it animate. Now, if you've ever written a game loop before -- and something like XNA is an example -- then this is the same type of process. You'll have something that fires over and over and over a certain amount of frames per second. And when it fires, update gets called to update the positions, and draw gets called to actually render the objects -- in this case on the canvas -- based on those positions. So that's a simple example of using animations in the canvas. And I showed how we can use either a timer or we can request an animation frame.
Demo: Using Gradients, Transforms, and Animations
In this demonstration, I'm going to show several of the different technologies that we've covered throughout this module, including things like gradients, transforms, and animations, and put all that together in a single HTML5 canvas application. So to get started, I already have quite a bit of code in place. And you'll notice that my onload after finding the context of our canvas calls a draw clock face and draw hand. Now, all this is going to do is display a seconds hand, but we're going to animate that. We're also going to have gradients involved and transforms. In fact, we're going to be using the transforms as we animate. So let me run it as is. And you'll see that we get a nice, little clock here. And we have a seconds hand. But it's obviously not animating. So what I'm going to do is integrate some timer-based animation first. Then we're going to talk about how do we trigger a request to an animation frame in the browser but on a time basis. Because normally, when you would call request animation frame, it calls as fast as the browser will allow. So if the browser can do 60 frames a second, then it will do 60 frames a second and call it that much. I don't really want that here though. I want to fire every second to animate the seconds hand around. So let's walk through the code first, and then we'll add some animation. So in the onload it's pretty standard. I'm going to calculate the center x, center y, and the radius of our clock and our canvas. And that's going to be used to render the different gradients that you see. The draw clock face renders the outer circle. And if you come down here, you'll see we have a pretty standard gradient that we covered earlier in this module. And we're going from our gray to white, and closing that path once we're done and that's just an arc that's being filled. And then in our draw hand, I'm calculating the position of where the hand should point to based on 360 degrees around the clock. And this is actually calculating the radians, though. And then once I do that, I render the area that is the blue area. Now, I clear it first, because we're going to be animating that inner section. Rather than clearing the entire canvas and re-rendering the clock and everything on the canvas -- which is pretty standard with animations -- in this example, I can get way with just clearing the interior of the clock. And so what I'm doing is just drawing over it right here with a gradient. And this is kind of a light blue to white. And I'm drawing an arc. And that represents the blue center of the clock. So that will overwrite anything in that area. Then on top of that, I draw the actual line. And the line to is based upon the radius and the position of where it draws is it going to be controlled by a translates. So we're doing a transforms here that translates the x and the y and then rotates it by the number of radians calculating up top here. And that's just based on the current seconds. Okay. So that's kind of how if I run it in refresh, you'll see that it will change. You can see that it's in a different position now. So let me refresh this. And you'll see it does move every second if I refresh it. Because that's doing a live calculation based upon the current time. But obviously, it's not animating it live. So how do we do that? Well, the easiest way is, instead of calling draw hand like this, we can actually come in and -- we can draw hand to start, but then right after that, we could do a window.set interval. And we'll give it the function to call draw hand every second. And that's really all we'd have to do. This will now trigger an animation that runs every second using the timer. So let's go ahead and run this. And you'll see that our clock now has a second hand that moves as appropriate. And that works pretty well. Now, if we want to integrate the functionality of request animation frame that we talked about earlier, we can do that. But as I mentioned to start this particular demo, that's a little bit challenging, because request animation frame actually fires as fast as possible. In fact, that's what we want. We want the browser to fire as fast as possible. There's no built-in way to call request animation frame on a time basis, but there's some nice shims out there that you can use. So let me show you an example of that. Towards the top of the code, I have the shim I showed earlier in the previous demo where we have a wrapper request anim frame. And that figures out which type of animation frame support we have, whether it's Webkit, Mozilla, Opera, Microsoft, or we fall back to just set timeout which calls it once. And that's nice. But that calls it as often as possible, and we need the little second hand clock here to actually go in and only move as the seconds -- obviously fire, once a second. So up on get, there's a really nice little shim script that has a request timeout and request interval wrappers. Now, what they do is they do do a timer, but they integrate in the ability to request an animation frame. And so what this will do is do a little bit of timing here and find a delta of the time, based on a delay we pass in. So we actually call it the same way as you would -- in fact, we can look right up on top here. When we call set timeout, you give it a callback in the number milliseconds. And that's the standard JavaScript timeout. Well, this one leverages that. You'll notice it kind of looks the same. You pass in a function. You pass in a delay. And then it will automatically calculate the delta and then call that function. But it will use request animation frame if possible, if it's supported. So it's a nice little shim. And you can see the URL for that here if you're interested in seeing that script and some others that are available there. So what I can do is we'll go ahead and rip out our timer-based example, and instead we're going to call into this request timeout. So let's come on down and write in our draw hand, just like we did the animate in the previous demo. I'm going to paste that in. And I want to call the draw hand. But I want to call that every second. So now this is kind of the best of both worlds. We're going to be using the request animation frame if possible. But we also have a timer going so that it just doesn't fire constantly as is the default behavior. So let's go ahead and run it. And we'll see the exact same behaviors. There's really no difference per se. But it definitely is more efficient, especially if we switch tabs. Basically, what will happen behind the scenes is it will request animation frame, it should shut down those resources until you go back. And then it will pick back up kind of where it left off here. So it provides a really nice way as we go back and forth to use resources efficiently and still have a timer. So that's a nice, little shim that's out there that if you're interested that, again, you can get at this URL. So that's an example of integrating gradients, transforms, along with animations, including timer based or request animation frame based.
Summary
This module's been all about working with pixels in the HTML5 canvas. We've seen how we can render pixels for gradients, whether it's linear or radial. We've talked about transformations and how we can actually move those pixels around, whether it's rotated or scale, translate, or even use the matrix algebra with the set transformer, transformer function. And we've also looked at how we can directly access pixels using functions such as create image data or get image data. Finally, we ended talking about animations. And although you won't find any functions in the canvas specific to animations, we can use timers or request animation frames to actually animate different items that are on a canvas.
Building a Custom Data Chart
Introduction
Up to this point in the course, you've seen several of the different API's available with the HTML5 canvas. And what we're going to do in this module is put many of those together in a single canvas application. And what I'm going to demonstrate is building a type of business chart using the canvas from start to finish. We'll start out literally with an empty screen and we'll add some code, add a lot of different features along the way including a lot of the key features we've already talked about like gradients, lines, circles, and more. So the official agenda shown here we're going to start off by creating a CanvasChart Object. And that's just going to be an empty Java script object that follows a pattern called the revealing module pattern to allow for better re-use and better encapsulation of our code and really simplifies maintenance down the road as well. From there we're going to talk about how we can renderText and gradients to start out with our canvas in our chart we're going to build. We'll learn about rendering different types of text as far as the individual data points and the individual lines, kind of the guidelines for the chart. We'll then render the actual lines for the data supplied by the end user, render the data points which will be some circles. And you're going to see the user will have an option to just rend the lines or the points or both. And then finally we're going to talk about how we can add animations into the mix and animate the points that will actually render on this chart and also show how those points as you mouse over them can have some interactivity and have some overlays to show the actual data. So let's go ahead and start off by taking a look at how we can create the CanvasChart Object that will represent our canvas.
Creating the CanvasChart Object
Before we jump into the code, let's take a quick look at the CanvasChart Object that we're going to create from scratch and show some of the different features that it offers. Now once it's rendered, this is what it will look like in the browser. So you can see it uses a lot of the different features that we've talked about throughout this course so far. We have gradients here and in our little circles, we have text used for the X axis, Y axis title and the data points. And then we obviously have lines used for the grid lines and then we also have the actual data point lines that are connecting the points here. Let me jump over to a live demo of this. And in this demonstration you're going to see that not only can we get to the stuff I just showed, but if I hit refresh, you'll see that we have a nice little animation of the actual data points coming on the chart. And in addition to that as we mouse over the different data points, you'll see that I have a nice little mouse over animation that shows and I show an overlay representing the actual data value for that point. In this case, the U.S. population for that year. As far as the features I've talked about some of the key ones, we can render lines and points. And we'll be using the standard moveTo, lineTo, arc and other functions that we've talked about. We can display text not only for the title but the X and Y axes and other areas. And then obviously we're using gradients a little bit to add that nice subtle effect into the canvas. We also, as I showed, have built in support for animations as that chart loads. We have the mouse interactions and the dynamic data overlay. And then in addition to that, once we get the actual code built, I'll show that the user of this code can actually build up a settings object they can pass in to determine how the chart renders. For instance, if they only want lines and don't want data points, then they can choose that. Or maybe they want both just like I showed in the demonstration. Now the script I want to build from scratch is going to follow a pattern called the revealing module pattern. One of the things with a canvas is as you start writing code, it can quickly get out of control when it comes to functions. And I call it function spaghetti code. In another Pluralsight course I have called Structuring Java Script Code, we cover this revealing module pattern in addition to some others. And this is the pattern I'm going to use to structure the code in the actual canvas application. Now as far as the actual API for the CanvasChart Object, it's very simple. The user that wants to integrate it into their web page can simply call a render function and pass in the canvas ID along with a settings object, a data object that holds not only the data that we want to chart but also some settings that control things like line versus point or both of those. We can control some of the different fonts and other things. And what this render function does is it handles initializing the overlay that I showed. It locates the canvas and creates that initial 2D context that we need to work with. It then does some really basic calculations to figure out what's the max X and Y for our data points. Because the pixels that we're going to be rendering aren't going to equate or match up with the actual data that the user might pass in. So we have to calculate a ratio to map the data onto the appropriate pixel coordinate as far as X and Y. And then once render does all that, it will give off some background functions, some private functions that will render the lines and the gradients and then ultimately render the data. Now I mention that the user is going to be able to pick what type of chart they want. If they only want lines, they can do that. If they only want points, they can do that. And that's controlled through a property in CanvasChart called renderType. And they can pass that in using this data object or settings and then the chart will dynamically figure out what type of points or lines or both that we want to render. So let's jump into a demonstration. What I'm going to do is start with an empty Java script file and then from there, we're going to start adding the shell and then as we move along in the different sections of this module, we'll keep filling in more and more code.
Creating the CanvasChart Shell Code
To get started you'll see I have a chart dot HTML file. And in this file I'm pointing to a script and this is where we'll be working the most. This is our CanvasChart dot JS, and then I have our own custom script here which is where we're going to use that and call in the CanvasChart and have it render. So we'll come back to this a little bit later in this module. Coming on over to CanvasChart, what I'm going to do is create a new object. Now we're going to use the revealing module pattern so I'm going to start off by creating the shell for our CanvasChart Object. We're going to assign this to a function and we're going to go ahead and end that function and then inside of here I want to go and add my different functions as well. So before I do that, there's going to be several variables I need throughout this particular object. So I'm just going to paste these in because they're really not going to be something I want to type by hand. And we're going to create those variables and then we're going to define our render. ( Pause ) All right. So there's our render and then we're going to go ahead and end that for now. That will ultimately end the var that we see way up here and I generally prefer to do this just have the var and put a comma to separate all my variables. But you can certainly do it the other normal way by putting var in front of everything if you want. Notice we already have a renderType here and then of course we have our render function. So what I want to do is come in and expose these and we're going to do that by returning an object literal in Java script. And this is following this revealing module pattern. So what I'm going to do is say when the external caller calls render, I'm going to forward that internally to this render function. And then I also want to expose renderType and we're going to call into the renderType variable that you see right here and all this is almost like an enom if you are familiar with that in other languages. But it allows us to have a property called lines which is just lines in a string form and points which is points. And that way the external user can go in and say if they want lines or points or both to be rendered when the chart kicks in. Now this revealing module pattern, oftentimes you'll see it like this. This is something I cover in the Structuring Java Script Code course in a lot more detail if you're interested. But for now what this would do is invoke this function immediately and basically make a singleton. In other words, we're only going to have one CanvasChart per page. I don't really want that here because it is possible we might want to render multiple charts on a page. So we're just going to do it this way and what they means is the consumer now would need to come in and do something like this. ( Pause ) And then we'll call chart dot render. We'll pass in our canvas ID which is just canvas here you can see. And right now I'm going to pass null. We'll come back to that. But this is going to be my data object. The data for the chart as well as the settings that I'd like to show in the chart. And so that's really all we have at this point. We have some variables, going to be using those as I start in fill in these functions. We have our render function which takes that canvas ID and our data or settings object. And we're going to be using that inside of here and then we're going to return. This exposes our public members of this object. Anything not exposed in this return will basically be treated like it's private similar to in C Sharp or Java or other types of objects oriented languages. All right. Now from here I'm going to go ahead and just paste in some more code because this is code that's a little bit boring, but we'll talk through it. What I'm going to do is store the data object passed in up here into this data object. And I'm then going to go in and we're going to define this function but we're not going to do anything with it until later. But I'm going to create a function down here called create overlay. And so we'll do that using this pattern so we'll say create overlay and that's just going to be an empty function for now. And we'll end it so we're going to assign our data which has our data and our settings. We're going to call create overlay which is going to be used towards the end of the module to actually show our data as they mouse over the different data points. Then we're going to do some pretty standard stuff. We're going to find our canvas and grab the height and width of it because that's going to influence the height and width of the chart, of course. I'm going to add an event listener for mouse move because we have that in interaction I showed and that's going to call a mouse move so we're going to go ahead and add that as well. And then we'll fill this in later. This is going to pass an event object. And once we do that, we're going to grab our context and we're going to be storing that context up here in this object level variable. Now the rest of the code just does some simple calculations. We're going to take the chart height minus our left margin which you can see the left margin is 75 plus the right. So we're basically grabbing the insides of the chart because on the left we're going to have some text. In this case on the right we actually don't even have a margin, but we could if we want to put other stuff over to the right. And that's going to calculate the actual size of the chart itself minus the margins, of course, for the X and the Y. And that is just going to substract off left and right or top and bottom margins to calculate that. Now the next thing we're going to do is I need to know the maximum Y value because I'm going to be writing out the different labels and if I don't know the max Y value, I don't know how much of a gap to put between the different labels on the Y axis. So I'm going to have this max Y value here that I'm going to add as well and that doesn't take anything. And what max Y value is going to do is actually iterate through the data that's passed in through this data object that we see right there. It's going to iterate through that and then return what is the maximum value of that? And again we're going to use that to determine the spacing and how tall to make this chart. So this is going to loop through our data object that I showed right up here. It has a data points that we're going to be getting to a little bit later. And we're just going to loop through those, and really we're just going to track the current value compared to what we have which the first time through would be 0. If it's greater than that, then we'll update max Y to that value and ultimately loop through the values and grab the greatest value. That's what this will do right here. Now, the next thing we're going to do is calculate the ratio. This little guy here is actually pretty important because the data points are not going to be pixel based. In fact, we're going to do U.S. population like I showed earlier. And so as a result of doing that, we don't have pixels. We just have in millions. So I need to calculate the ratio from the Y max which is the chart's max to the max Y value of the actual data and that ratio will let us then determine how the data points that are passed in map to the X or in this case the Y coordinate of our actual chart since the chart is pixels but the data being passed in is not pixels, and that just does a simple calculation. And before I go too much further, I just realized that max Y value should call get max data Y value so I need to rename that and that will definitely be a lot better. Now the final thing we're going to do is we need to make sure that we render something. It wouldn't be too exciting if the chart just rendered some lines without the actual data, though, and some labels. So the data renderTypes is something that is passed in through this data object that gets assigned again to the data here. And that's our settings and our data for the chart you'll see. And as renderTypes, if it's undefined or if it's null, we want to go ahead and default to at least draw in the lines. Otherwise, nothing gets rendered and the user would probably be confused as to why chart is not rendering anything when they passed in some data to it. So that will kind of take care of that. Now once all that's done, we're going to come in and we're going to add a little private function in here called renderParts that we're going to call. This is actually going to do all the work of rendering the individual parts such as the background and the lines and the labels and eventually the data. And we'll be doing a lot of additional code and functionality as we move through this module more. But for now I'm just going to add a renderParts and we're going to leave that empty for now. All right. So that kind of wraps up this first part of the demonstration and the shell for this particular CanvasChart. So we have all our variables defined. We have a public render. We know that's public because of the revealing module pattern and we have that defined in our object literal that starts and ends there. When render is called, we're going to go in and assign the settings that were passed in up to our data object here and then we'll find our canvas, do some basic calculations, make sure that we have something to render as far as lines or points and then call renderParts. Now we'll be filling in renderParts and the overlay in the mouse move as we move along. But that wraps up this particular demo and shows how we can create this initial object. Now we could use this object. It's not going to do anything at this point. But we can run it and it should fire up a new CanvasChart. Target this canvas that we have here and then once we pass in the data, it will render it.
Rendering Text and Gradients
Now that the CanvasChart Object's been created, we can start to add some additional functionality into such as some of the text for the chart and the background gradient for the chart. So what I'm going to do is create two new functions and those functions are going to handle those individual tasks of the text and the gradients. Let's go ahead and jump in here. Up to this point you've seen the CanvasChart Object and that it has a render function. Now when render's called after we get the context and set some values, we're going to call renderParts. And that's really the engine if you will of our CanvasCharts. It's going to kick off all the other subfunctions to do things. So you can see I've added two new functions in, renderBackground and renderText. Now the background is going to render the gradient and the text is going to render some of the different labels that will show for our canvas. So let me paste in some code here for renderBackground and you'll see that this creates a linear gradient based upon as far as the positioning the margins. So if we come up top, here's where we have our top left, right and bottom margin values, and we're going to use those values to control the gradient here. Now we're also going to come in and set a cue color stop. So we have kind of a light gray to white and then back from white to light gray. It's going to start in the upper left-hand corner and that's our margin left, margin top. And that's going to go to the bottom right-hand corner. So it's going to be kind of a diagonal from left to right and these values here calculate that. And so we'll start up in the upper left-hand corner with a gray and the bottom right-hand corner with a gray but the middle where most of the chart will be will just be white so it's easier to read the data points and things. Now once we add those color stops, we're going to go ahead and assign them to the fill style of our context and then we're going to fill a rectangle. And this rectangle you'll see is positioned almost identical to what we had up here as far as our margin left, margin top, and then we're going to calculate our X max margin right and our Y max but we're going to substract off that top margin here. So what this will do is it's going to create a gradient. It's going to fill it into a rectangle and then after that we're going to go ahead and set the fill style back to black because from then on we don't want to use this particular gradient. Now if I go ahead and run it at this point, let me switch back over after we save, you'll see that we get our nice little gradient so it starts in the upper left-hand corner and then down to the right and it's mostly white in the middle you'll see. And the reason this is working now is because earlier in the previous section, I just passed null right here. I didn't have any data or settings. Well, this time what I've done is set up an object literal and you'll see I have a title, some animation values. X and Y label values is going to be our label font. We're going to use 4 of those. Data point font. Here's how we control if we want lines and points and in this case, we want both. And then these are the actual data points that will go on the chart so this shows the U.S. population from 1790 up to 2010 and these are going to be the data points. Of course this is in millions so we're going to be converting that to pixels. And I talked about that a little bit earlier in the previous section. Now what we are going to do with this data and settings object is pass it in. That then comes on in and becomes our data object. Now that's important because now I'm going to update the code for the renderText. So let's come down in here and paste some code in. And you're going to see data dot quite a bit in here. So first off, we're going to determine did they pass a label font in. If it's not null, we're going to use it. So that came from right there. So right now we're going to do 19 point aerial. If they didn't pass a value, we're going to pass 20 point aerial. We're going to assign that to the context font and set the alignment to center for the text align. And what that will do is put it in the middle very easily for us. Now we're going to call fill text, take the title. So our title, if we switch on back, is right here. U.S. population chart and that's what's going to be written out. We're going to start it in the middle of the canvas. We're going to take the chart width divided by 2 and then the margin top divided by 2. We want to put it kind of in the middle of the margin at the top and then we're going to center it on the canvas itself. Then we're going to come in and we're going to take the X label. Well, if we come on back, the X label is year; the Y label is population in millions. So if we come on back, we're going to measure that X label and the reason for that is I need to know how wide it is. So when we fill text, we're going to fill the X label text. We're going to take our left margin because we don't want to start rendering at that point. We're going to add on the center point of the chart and then subtract off half of the width of the actual text. And so we basically factor out the left margin here, find the center point of the chart, including that left margin, and then subtract off half of the text. And that will center it right in the middle for us, of that chart. And then for the Y, we're going to take the Y max which is the bottom of the chart and add on the bottom margin divided by just a little bit. All right. And our bottom margin currently is 75 pixels. So we're going to go a little bit bigger than that it looks like. All right. And that will render our X axis text. Now for the Y axis, this needs to rotate up to the left. What we're going to do is save the current state of the context, and then we'll restore it right down here. We're then going to rotate backwards. So we're going to go basically 90 degrees over to the left. And then I'm going to say, let's assign the label font again which we already had, so technically I can probably skip that. We're then going to fill the text with our Y label. Now the text that's going to be rotated is this population in millions. And so that's going to calculate the Y max divided by 2. And we're going to multiply it times minus 1 because we're going negative here with our rotation. And then for the Y, we're doing margin left divided by 4. Now that might seem backwards. By rotating, we've now kind of changed the axes around. And so you'll notice that the Y is actually going first and then the X is going next because effectively we've switched those by doing our rotation. And that's a little tricky when you first do this. It's something I definitely struggled with when I first learned how to work with the rotate and the save and the restore. Because you have to realize that when you do that rotate, you're actually changing your coordinate system some. So that handles rendering our title down to here, our X axis text, and then our Y axis text. And then, of course, our Y axis text is going to be a little bit specializing and rotate up to the left. Now, of course, once we're done with that rotation, we want to restore the canvas to the original state which gets our X, coordinates back to the normal coordinate system. All right. So let's go ahead and save that, and let's run what we have. So now that we have this data and settings object being passed in, we should now see our gradient. And then you'll notice we have U.S. population; we have year on the X; and then here's our population in millions and you can see that the rotation took effect there. So that's an example of adding our gradients and our text. Now we're going to keep moving forward and in the next section, we're going to look at rendering some of the guidelines and some additional text on this chart.
Rendering Data Points Text and Guide Lines
Now that we've added the text labels and the gradient to our CanvasChart, we're going to go ahead and render some additional functionality and that's going to be the text for the different data points along the X and the Y axes and we're also going to render some guidelines that will be some horizontal lines that will show to make it easy to see how things match up with our text as the actual data is rendered which we'll be getting to in the next section. So let's go ahead and take a look at what we have up to this point. So in the previous section we went in and added the labels for the title, the Y axis, and the X axis; and what we're going to do now is add some guidelines that will be in here. And we're going to start rendering the text along this side of the chart and along the bottom of the chart. And that will be the goal of this particular section. Let me switch over to our CanvasChart. And what I'm going to do is add a new function in that will handle doing all of this rendering. And this function is going to be called renderLinesAndLabels because well, that's what it does. So let me go up to our renderParts. And right under this, I'm going to say "renderLinesAndLabels." And then we're going to pass in a bouillon value because sometimes we may not want to render the actual text and you'll see where that's used as we get more into the animation side of it. I'm going to go ahead in this example and pass "true." We're going to add this new function, renderLinesAndLabels. Now, this function is going to calculate some additional data points which I'm going to paste in here. And this is going to be a Y increment value because we're going to be writing some text out and some guidelines along the Y axis and we want to be able to move that Y coordinates. So we're going to take the max Y that we calculated earlier right up here at top which took into account our chart height and the margins. And then what we're going to do with that is divide it by the actual number of data points. Now as a review, the user is going to pass in this data points array. So we're basically going to get the length of this. That will give us the gap. So for instance if we had 100 and we had 10 data points, then of course we'd have 10 different slots we need to fill with 10 times 10. So let's come on back now and that's going to take care of that here for the Y increment. Y position is going to start at 0. Then we're going to call this X increment. And what that's going to do is call this guy which I already put in here. And all it does is the same thing. We're going to calculate how wide are we and divide the data point's length and that will take care of that. And we're going to go ahead and round it. So that takes care of those positions. And then we have our X position is always the margin left. I think that's around 75. If we look up here, we can see it right there. So we want to start rendering this basically at the location of the right side of the left margin. So that will take care of that. Now the next piece I'm going to put in is a little bit more code and this is going to be a loop. It's going to loop through the different data points that are passed in. And what we're going to do is increment our Y position. You can see if i equals 0, we're just going to position at the top. Otherwise, we're going to increment by Y increment here. So for the very first one, we just want to make it right at the margin top goes down to. Then we're going to call, drawLine. Now drawLine is just a reusable function that we can use and it, well, pretty much does what it says. So let me go ahead and add this is. So drawLine you can see pretty much takes the point and this is going to be a literal object I pass in as well as the stroke style. So we're going to do just do some really basic line drawing here and this should look really familiar based on what we covered earlier in the course. So I have the stroke style that's going to be set up. If nothing's passed in, we're going to default it to black; otherwise, we make it a little bit dynamic. The line width is going to be 1 of this. We're going to start our path and close our path. Then we're going to move to, on this point, there's going to be an X and Y, and then an X2 and a Y2. Now if I go back up in our loop, you'll see that I create that right there. There's our object literal. So the X is going to start at the left; the Y is going to be wherever the Y position is; and then we go to the X max and the Y position. And what this will do is draw a horizontal line, kind of a guideline if you will across the grid every time it loops. And then this Y position is going to get incremented. So it's going to move it down and down and down and down. You can see the Y changes based on the Y position. So when I run this, I'll show you an example of how this actually works. Now moving on down, if should renderText is true, which is the parameter passed in here, we're going to render the Y axis labels for, in this case we have on the Y, the millions, the number of population in millions for this example because we're passing in -- you can see the X is the year and the Y is the millions. And so we're going to set this up. So we're going to set the font you can see, the text; we're going to calculate some info about this. We're going to measure the text and then we're going to go in and do fill text. Now this value here is going to be based upon the actual data that we get as we're looping through this. But we're going to take into account the ratio. Because we need the map the data, and the data again would be like 3.9 million. Well, that's only 3.9 pixels. Not quite what we want because it depends on the height of our canvas. So what we're going to do is take that ratio so that we know basically had to equate what's the ratio between our pixels and our millions or whatever number is given. And that's going to be used to write out the text for this. Then we're going to come in, measure the text so that we can get the width right here and this will position it. Now I won't talk through every little part of the positioning but here's our X position there and then we're doing our Y position, and adding a little bit of padding to it, 4. Then we come on down and do the same thing for the X. We're going to come in and grab our data points. We're going to get the X now. And that's going to be the actual year that we want to write out here. And we're going to measure that and then fill the text. Give it the X and then calculate the Y dynamically and then increment the X position just like we do the Y position. So basically we're kind of doing like 2 things at once. We're drawing some guidelines; we rendering the Y axis labels; and we're rendering the X axis labels. Really the key functionality here based on what we covered earlier in the course is that we have a fill text and then in drawLine, we're, of course, doing the moveTo and the lineTo based upon what's passed in for this point which is just our object literal. So you can see our X, our Y, our X2 and our Y2, and those are used right there to calculate the line. Now the final thing we're going to do is draw out the vertical, kind of the left side of the grid or chart I should say; and then the horizontal line for it. We're going to call drawLine again. So you've already seen that. We're basically going to say the coordinates of the X and the Y for starting and ending. And that will draw a vertical line and a horizontal line here. So let's go ahead and render it at this point. And it looks pretty good. So you will note that we have on the left here, it basically calculated what was our Y max value, divided that and figured out the ratio and all that to get these numbers. And then we have these grid lines you can see. So 309 basically equates to that one, 258 that one, 232 that one, and on down. And the grid lines add just a subtle way for a user to easily be able to pick up on the actual position in millions of where this is. So this takes into account that ratio so it keeps it accurate as we're going to start rendering our chart. So that's a wrap on this section covering how to draw some guidelines in the chart and how we can render the X and Y axes text. Now, we're going to start jumping into how do we actually render data in our chart.
Connecting Data Point Lines
Now that we have all the gradients, text, our labels, and our different guidelines that are on our chart set up, it's time to start rendering some data to the chart at long last. So that's what we're going to cover in this section. And specifically I'm going to focus on how can we render data points for the actual line that will show in the chart. Let's go ahead and jump in. So I've added an empty function here called renderData. And this is going to be responsible for iterating through the data points and actually getting the X and Y coordinates of those individual data points. And remember we have to take into account not just the raw data but also how that data equates to the pixels that are rendered on our canvas based upon a ratio between them. Otherwise, 3.9 would be 3.9 pixels but in reality that might be 100 pixels. So we have to do that mapping. We calculated that earlier and that's something I covered earlier in this module. So the first thing I'm going to do with renderData is we're going to call it. So we're going to come back up to our renderParts, and we're going to call, renderData. Doesn't take any parameters. That will just kick it off. And renderData is then going to go in and it's going to iterate through our data objects, data points. So we're going to iterate through these different data points; and we're going to do some mapping from the data that we see here to the actual real X and Y coordinates of where the points should appear on our chart. So coming on back to renderData, I'm going to add an X increment so we're going to move from left to right as we actually work with this data. And so we're going to call a function we've already done earlier called, get X inc. I'm going to add in 2 more variables here. So we're going to call these previous X to track the previous X position, and previous Y to do the same thing for the Y -- let me fix that real quick. And that will also be 0. All right. Now from here, I'm going to paste in some code. And this code's going to now iterate through all our data points that are passed in by the user of this component. And what we're going to do again is we're going to push those up to an array we have up top here. And you'll see as we look up top here, we have this final data points and that just represents the final X, Y coordinates on the actual canvas when we take into account not only the data but also the pixels, and the size of the canvas, and the height, the width, and the margins, and all that fun stuff. So coming on back down, you'll note that we grab the point. And this represents our data point. We're then going to calculate our Y position. We're going to take our max Y and subtract off our point Y. And that's because we need to move the Y to the position where it will be on the canvas. That's because the Y always goes obviously from 0 at the top down to bigger numbers as you move down. Then we're going to multiply that by the ratio. That's really important because the actual data we're plotting for the Y needs to be mapped to our coordinate system of our canvas meaning that we have to convert these numbers into some type of a pixel number that we can render again based on the height and width of our canvas. So that takes care of doing that calculation here. Now from there, we'll do some other checks for the Y and then we're going to calculate the X and so we're going to take the i as we loop through each one times the increment that we have up here. And X increment was one from earlier where I just calculate the X max and divide it by the number of data points. So again if it was 100 as far as the width of the canvas, then we'd divide that by say 10, and we get 10 and that would be the spacing between the data points we're going to be drawing here so that looks nice and kind of compact. So what we're going to do with the X and Y values is we're then going to feed those into a data point. You'll notice these are some custom properties that I've added so we have an X property which is our X value, a Y property which is our Y, and then current X is going to represent where are we currently which is going to start at margin left as far as where the current X begins. And then X2 is going to be where were we before when we loop through. And you'll see that we start at 0 for both of those. And then previous Y is the same type of thing. And then we have the original Y is the actual data, the raw data that was passed in. Now this is going to be used a little bit later as we start to do the mouse interaction and show the overlay because if the actual Y position on the coordinate system was 100 but the actual raw data was 3.9, I don't want to show 100, of course, when I mouse over. I want to show 3.9 because that's the raw data value. So that's what that's going to represent. So what we're going to do is push that data point up into the array. Then we're going to go ahead and set our previous X and Y. Now we need these 2 values. And we need them because as we render our actual data, you can see that previous X and Y here, we're going to drawLines. So we're going to moveTo and draw a lineTo, and we need to go from the previous position to the next position. Now the final thing that happens is that once all that data is pushed and we've iterate through it, we're then going to check, hey, is renderLines turned on by the end user? And if you recall, they can do 2 types of things. They can do lines or they can do points. And if they supply nothing, we'll convert to at least renderLines. So coming back in, we're going to call drawLines. Now this is going to loop through those final data points which has the actual real data mapping the raw data to the coordinate system of our canvas. And we're basically going to call, drawLine. Now drawLine we used earlier. That was used to draw the guidelines and the vertical and the horizontal lines for our chart. So we're going to re-use the same exact function here. And what that's going to do is then take our data point which is the same type of data point I used earlier, if we come back and just as a review, look at renderLinesAndLabels, we're creating a very, very similar data point here. We're going to use that function to actually render our lines if the user wants lines. Now they don't have to have them, of course. But we're going to assume, at least for this purpose that we have lines and points that we want to render. So that's kind of a wrap on what's going on. So as a review, we come back up, our renderParts renders our gradient. It also renders our text. We come in and do our lines and labels along the X and the Y axes; and then we actually start rendering the data. Now there's a little more to this story and I'll get to that in the next section because we need to render the data points, of course. But if we jump down to renderData, this now iterates through the data, creates the actual coordinate map of the X and Y of where it's going to go on the canvas, pushes that into an array, and then we're going to iterate through that array to draw our lines. Now that you've seen all that, let's go ahead and switch back over. We save everything and we'll run it. And there we go. So you can see that we now have a nice little line that's going up to actually show the U.S. population growth from 1790 out to 2010. And there's individual lines. You can't really see them because it's a very gradual, you can see, increase here. But there's individual data lines drawn between these different points of the years and they're being connected very nicely using the process that I just went through. So that's a wrap on how we can draw the data lines. In the next section, I'm going to show how we can actually render some points on top of this line.
Rendering Data Points
Now that we're plotting our data using lines, we're going to add some data points onto the canvas. Let's go ahead and talk about how we can use the arc function to render some lines on our chart based on the data that's received. In the last section, we added the renderData function into renderParts, and let's go ahead and go down to that. Our renderData then calculated some positions and ultimately filled the final data points array that's at the top as a variable, and we push in the data points into that that we create right here. And then from there, we call drawLines. Now what I'm going to do in this particular section is show how we can draw some points and this is something we've covered earlier in the course when we talked about the arc function, that's what we're going to be using. So let me cut and paste this down. And what I'm going to do is check if the user specified that they want points. So we're going to call drawPoints if they did. And the drawPoints you'll see I already have in here along with another function called renderCircle. Now renderCircle is going to create a radial gradient, and it's going to add in either a highlight color that's supplied or it's going to default to green if one's not supplied, and then kind of go from green to white on the gradient. We're then going to begin our path. We'll close it down here and then we're going to render an arc. And then on that arc, we're going to stroke it. We're going to put a small border that goes all the way around it. Now we need a way to call the renderCircle so I'm going to come back up to drawPoints and we're going to do a simple 4 loop here. So we're going to start at 0 and we're going to loop through our final data points that we have up here. Let me go ahead and grab this. We're going to do while i is less than final data points dot length, and we'll increment by 1. We're going to say final data points and we'll grab i there; and then we'll call renderCircle. Now you can see renderCircle takes an X,Y in a highlight color. I'm not going to pass a highlight color in this particular demo so I'm going to pass point dot X and that comes from up here again because we have our X and our Y. And this is going to specify the X and Y coordinate of the center point of the circle, and then we'll pass point dot Y, and that's pretty much it. So that will call in pass in the X and Y, and then from here, you can see that the arc function and the create radial gradient is using the X and the Y here to specify not only where the gradient starts and ends but also where the arc actually starts. And then our point radius is at the top here. You'll see our point radius is currently set to 10. Now that's something we can certainly enhance to allow the user to pass that in as a property. But currently it's just hard coded to a value of 10. So if we come back down to renderData, we're first going to render the lines. Now the reason I'm doing the lines first and looping through that and then looping again is if I do a line, then a point, then a line and a point, the line will actually overlay part of the point or the arc, the circle that we're doing; and it won't look like what we want. So we have to render the line first. Otherwise, I'd have to figure out kind of a little gap to leave in the line, but we don't want that because the user may not do points. They may just do lines and so we're going to give them the option to do both and still look good. When drawPoints is called, we iterate through the final data points that was created as we iterate through the raw data in our data points. And then we're going to call renderCircle for each point. And that's pretty much it. So we have all our functionality now to render points. So let's go ahead and try to run this. And you'll see we now have lines with some data points on those lines. So now we're going to do is switch gears. We have our chart completely rendered at this point. We have our labels, our axes text, our line, and our points. But what we're going to do to wrap up this module is learn how we can animate these data points. And also how can we make it so that when the user mouses over one of them that not only does it highlight it with a different color, but it also shows a nice little overlay representing the raw data for this year. And that's what we'll be looking at in the next 2 sections.
Adding Animation
The CanvasChart object is looking pretty good. We're rendering our lines and our data points, but in this section, we're going to take it up a notch and we're going to work with animations. Now earlier in the course I discussed how animations work and how we actually have to clear the canvas and re-render and clear, and re-render, and we have this kind of game loop if you will that we work through to animate things. Animation is not built in directly. So it's up to us to write the code to do it to manipulate these pixels. Well, that's what we're going to talk about, and we're going to talk about specifically how do we animate those green data points that were on the chart. So let's go ahead and jump in and take a closer look at how we can do that. Currently the drawPoints function iterates through our final data points which represents the actual X,Y coordinates of the points we want to plot. But it just renders a circle. So there's obviously no animation going on because we just write out the arc, we fill it, and we stroke it to give that border. Well, what I'm going to do is come in and enhance this a little bit. We're going to say if there's a property set on our settings object which also holds the data called animate points, then we want to go ahead and do something a little bit different. Else if there's nothing set for that, if it's false, then we're going to go ahead and just write those out and not do an animation. Now this is already defined if I go back to the CanvasChart, we can look in here and you'll see in the data and settings, we have animate points and we have animation speed. And these are 2 properties that I'm going to basically use to go in and animate those data points right as the chart first loads. And so going back into our drawPoints, what I'm going to call here is a nice little function called animate. Now we currently don't have an animate function, but that's something I'm going to add. And what the animate function is going to do is handle the clearing and drawing the lines and all the background stuff including the gradients, all of that. And then it's going to move pixel by pixel those data points over. So let me go ahead and paste in some code for animate and we'll talk through this. So the first thing I'm going to do is say, is there an animation speed set? And that goes back to here. Currently the animation speed is 20. The higher it goes, the faster the points move. If you did 1, it would be really slow. So we can come back into here and say if it's null, we're going to default to 20. Otherwise, we're going to use animation speed and that lets the user kind of play around with that and get it how they want. Now from there, we're going to request an animation frame. To request an animation frame, we need to be able to count on the browser supporting animation frame capability and this is something I talked about in the animation section earlier in the course. And unfortunately not every browser supports that at this point. So I have a really nice polyfill that I'm going to add. We're going to add that right below our canvas objects. Let me paste that in. And here's the RO where I grabbed it, and what it's going to do is iterate through the window object and check if request animation frame is there, and if it is, we'll go ahead and use it. It's also going to work with something called cancel animation frame and that will stop the browser from giving us frames that we can render animations to. As a last resort if none of that is supported, then we're going to fall back and we'll do a set time-out. And that will get called and then whatever milliseconds it is, say it's, you know, 200 milliseconds or whatever. Every 200 milliseconds then we can cause this to fire. But for the more modern browsers out there we'll have support built in to automatically allow this type of functionality to work. So this is the polyfill we're going to be using. Now if we go back up into our animation, we call request animation frame off of the window object so I could have done window dot and that would have worked. But we don't need to put that specifically so we're just going to call request animation frame and we're going to give it this function. So when it gives us a frame, it's going to call this function and then we'll repeat the process over and over and over. Now that's going to give us back a timer ID which I said is a global variable of this particular chart object, and we track it. Now the next thing we're going to need to work with is we need a way to clear out the contents because I can't just animate the circles or the points. So we call a function called clear right here and what clear is going to do is clear the rectangle as you can see here based on a very specific positioning of our X and Y coordinates and the height and the width. And it's going to do that so we only clear actually where the gradient is. So we're going to leave the text on the left at the top and on the bottom. And the reason for that is we can save ourselves a little bit by not having to re-render the transform of the Y axis to X and those types of things. Next thing I'm going to do is call renderBackground. If you recall, renderBackground, we jump back up to it, handles our gradient and that's what we looked at earlier that goes from gray to white. After we do that, we're going to call renderLinesAndLabels. But notice we pass false for renderText. So if we come on back up to that, here's our renderLinesAndLabels, show renderText is false which means we're going to skip all of this. So all we're going to do is draw our guidelines but we're not going to re-draw the X and the Y axis data points for the text. Those are not in the way. They're not where the data points are being rendered and animated. Therefore, we can just leave them. And so that's why I added this little bouillon in here so we can still reuse this function. But it's just going to draw the lines for the guidelines and for the vertical and the horizontal line and that's it. So once that's done, our clear takes care of clearing everything out. We're going to call drawLines and that will go in and render the data points using our drawLines function. So we need those first and then we're going to animate on top of that our data points. So we're going to loop through our final data points that holds the actual X,Y coordinates, grab the point and then move it over by the speed. So it could be by 20 pixels at a time or 5 pixels at a time or whatever the user sets. And then if the current point of the current X of that equals the X that it should be at. So in other words, if where we're at with this current X is either greater than or equal to where it should end up on that graph, then we just want to make sure current X is that data point. And then we're going to go ahead and render the circle using the current X which means basically if we're at that point, that stops animating for that one, and the Y. Now if the length of our data points and we're going to subtract off 1 equals the i, we know we're at the end of the loop here, and the current X equals the point X which could have happened as a result of this, we're going to call cancel animation frame and pass in the timer ID. Now that will jump back down to our polyfill and we have a cancel animation here which can clear a time-out or if cancel animation frame is supported natively it will just call that on the browser. So that is our little animation routine that goes on. So now as a review, when drawPoints is called here, we're going to check if animated points is true. If it is, we're going to call animate. Otherwise, we write out the static points. If animate points is true, we're going to call animate, we grab our speed, and we say, hey, browser, give me an animation frame so we get that smooth animation hopefully. And we're going to give it ourself as the callback. We're going to clear everything behind it because otherwise the data points if we didn't clear it would look a little bit weird. We're going to draw our data lines and then we're going to iterate through and move over our X position of our point, point by point by point, and then we'll use that when we render the circle. Let's go ahead and save this and let's try to run it and see what we get at this point. And you'll notice we get a nice little animation there. Now just to show you what would happen, let's come back in and comment out clear. Let's re-run it again and you'll see that it truly is animating everything, pixel by pixel, and moving those over. So if we don't have the clear then obviously it looks a little bit weird. And I don't think that's the type of chart that we want at least in this example. So that's why we have to clear. And really what we're clearing is right here down to here and right above the text and right over to that edge. And that's actually what we're clearing. That way I don't have to re-render the title and all this stuff and all this stuff, and it saves a little bit on the processing power. So let's go ahead and go back. Let's put back clear. We'll run it again and we get our animations. So that's an example of how we can apply some of the animation techniques that we talked about earlier in the course into our CanvasChart Object.
Adding Overlays and Interactivity
The CanvasChart Object now renders data and we have a way to do some basic animations of the data points. But for the final interactivity piece, I'm going to make it so that the user as they hover over one of the data points, can see a highlighted note so it turns from, in this case, we're going to go from green to red. And also I want to show an overlay that represents the data for that particular data point so they don't have to guess what it is by looking at the chart and the different guidelines and numbers that are available. So let's jump in and I'll show you how you can do that. When we first started writing our CanvasChart object, I added a render function and it had a call to some empty functions, create overlay and mouse move. Now create overlay in just a moment you're going to see is used to show a div representing the actual data value of the point they're hovering over in the canvas. And then our canvas has an event listener attached for the mouse move and that's going to call down into the mouse move. Now that one I've already put into play here and I have the code added so let me jump on down. And here's our mouse move you can see. Now this is going to pass an event object like a standard dom event. And from this, we're going to get the X and the Y coordinates of where the mouse is when it actually moves. So we're going to do that either using the offset X and then the offset Y, or layer X and layer Y. It depends on the browser here. Now most browsers support the offset X and the offset Y that you see here. Now we're going to make sure that those positions that we just found are greater than the margin on the left and greater than the margin on the top. Otherwise there's no reason to waste time doing all of this processing. Now this part's a little bit tricky because you actually have to write code to say, is that mouse coordinate inside of one of those data points which means I need to actually calculate where each data point is, calculate out the radius from the circle of the data point, and then go from there. So what I'm going to do is loop through all the data points, grab each point and then take the X of that and subtract off the radius, that will kind of go to the left. Add on the radius and that gives us, going from left to right on a horizontal view, the size, kind of the min and the max if you will as I named them here. And then we're going to do the same thing for the Y. We're going to go to the Y minus the radius and the Y plus the radius to give us the min and the max. We're basically drawing kind of a box, a square, over where that data point would be, at least in memory here. Now we're going to say if the X is greater than or equal to the min, less than or equal to the max, then the same thing for the Y, then we must be inside of the data point. So we're going to call into a function called clear circle. Now I don't have clear circle in there currently, so I'm going to go ahead and add that. And actually let's add that right above here. And clear circle simply goes in based on those X,Y coordinates, it begins a path and then it's going to do a fill style of white to clear it out. And we're going to draw an arc and fill it. So that just literally just kind of takes that green circle that we currently have or whatever the user supplies for that, and we're going to go in and clear it out. Now I had to clear it out; otherwise, what will happen it will start to build on top of each other and it looks a little bit messy. So by clearing it, it looked a lot cleaner. Now after we do that we call our standard renderCircle, that's the one we already added earlier. You can see that right here. Now this time I'm passing a highlight color though. You can see that for this color stop, the highlight color is null, we're going to default to green. Otherwise, in this case, we're going to pass red. So we're going to use red as our highlight for our color stop and go from red to white. Now from there, I'm going to track the current point that was selected. I need that because eventually when they mouse off of it, we need to go back to the green. So I'm going to track selected data point up at the top. And then I'm going to call, show overlay. So we'll place that right in here. And what this is going to do is grab the original Y value. Now this goes way back earlier in this module. When we come back up to our renderData, when we create each data point that gets pushed into the array, we track the raw data. Again, this would be the 3.9, the 7.2 because if you recall those don't actually match up to the pixels. But from the end user standpoint, that's what they want to see, of course, for the data. So what we're doing here with this overlay is the show overlay goes in, grabs the original Y, and assigns it to this overlay divs, enter html. Now the enter html is just going to be like normal dom. This isn't canvas at this point. So what we have here is down below, I added this overlay div. Now currently you can see the display is none. We're going to update the html of it so that we can show the actual data point. We're then going to position it based on the X and the Y coordinate that's passed in to this show overlay. And then we're going to go ahead and display it. And that will take care of handling all the work that we need done there. Now of course we need to have that overlay so you'll notice right at the top of render -- I mentioned when we started this section, we have this create overlay. Now all that does is it goes and finds this div, loads it up into memory. Let's go back down to the create here and I'll add the code for this. So this goes and finds a div if we supply it. Now in this particular case, I could either have the user pass in an overlay. Right now, it's not set up to do that but we can easily set this up to pass in this guy here. And this is mainly put in to show you kind of what it's really doing. But behind the scenes what I'm doing is dynamically generating the div. We're setting the display to none, setting a background color of a light gray, border position is going to be absolute because it's going to absolute position the top and the left, add some padding, and then append that into the document body. So really what it's doing though is like I showed you, this div here is just being created dynamically, either hard coded in the page or you can do like I'm doing here and dynamically add it. That way the user of the CanvasChart object doesn't really have to worry about adding that. Now if they wanted to set up their own styles and such, then you can definitely as I mentioned add a property here. And then instead of running this code, you can just assign overlay div to the div they pass in. So that would be something that would be very easy to update this control with. And that's pretty much it. So when render gets called, we're going to create that overlay. We're also going to hook the add event listener to mouse move and mouse move is then going to come in -- there's one more thing I want to point out here. And it's going to check if we're on the circle. Now if we're moving off of it, if we're outside of the bounds of the max X and min X and same for the Y, then if the selected data point is not null, so if we were just on the circle, we need to clear it out. So we're going to hide our overlay, clear the circle, and then re-render that, but this time, we're going to re-render it using the green because I didn't supply a highlight color here. So let me go ahead and save this. And let's run it and see what we get. All right. So you can see as I hover over, I get a nice little mouse over effect. A little bit tricky to do compared to normal dom manipulation. And then I also get the overlay div. That's 62.9, 92.2. Those are the actual values. Here's the 62.9 and the 92.2 that the user would expect to see. Makes it very, very easy for them to hover over this and get to those different data values. Now this would be a little tricky to do. It would be possible to do this div or this box I should say with just pure canvas because I'd have to clear it and that means re-rendering everything. So while you can certainly do this, doing a div is usually the easiest way because that way I don't have to worry about clearing the canvas every time that div or that square dynamically shows. So that's an example of adding some mouse interaction in an overlay for our CanvasChart Object.
Summary
In this module, you've seen how to build a custom object from scratch called CanvasChart. And you've seen how we can use all the features that we've talked about earlier in the course in one nice little canvas application that renders data and renders this type of business chart. So we talked about how we can render lines and points using things like moveTo and lineTo and arc. We talked about rendering text using fill text. We rendered different types of gradients including linear gradients and radial gradients. We also talked about how we can do animations which although they're a little more work, they definitely perform quite nicely with the canvas API. And then we added some mouse interactions and dynamic data overlays. Now all of this was made somewhat flexible by a data settings object that the user can pass in. And we saw that the overall script followed the revealing module pattern. Now the CanvasChart Object certainly is not the be-all, end-all type of script. There's a lot of refactoring that I think could probably be done and a lot of new functionality. But it should help get you started applying multiple types of canvas API functions and seeing how those can all work together in one cohesive application.
Course author
Dan Wahlin
Dan Wahlin founded Wahlin Consulting, which provides consulting and training services on JavaScript, Angular, Node.js, C#, ASP.NET MVC, Web API, and Docker. He is a Google GDE, Microsoft MVP and...
Course info
LevelIntermediate
Rating
(264)
My rating
Duration4h 32m
Released12 Jun 2012
Share course