IntroductionWelcome| 00:03 | Hi! I'm Joe Marini, and I'd like to welcome you
to HTML5: Graphics and Animation with Canvas.
| | 00:08 | In this course, we're going to learn
about the new canvas element, which brings
| | 00:12 | sophisticated graphics
capabilities to HTML5-based web pages.
| | 00:16 | First, we'll take a look at some
real-world web sites that are using the
| | 00:20 | canvas element today.
| | 00:21 | I'll show you how to incorporate a
canvas element into your page and draw
| | 00:25 | basic graphic elements.
| | 00:27 | Then we'll move on to more advanced
drawing features like gradients, patterns,
| | 00:31 | and transformations.
| | 00:33 | I'll walk you through creating a
canvas-based animation from start to finish.
| | 00:37 | And finally, we'll see how incorporate
a canvas-based solution into a real web
| | 00:41 | site using free tools available on the
web today, such as jQuery and modernizr.
| | 00:46 | With the HTML5 canvas element, Web
developers finally have many of the same
| | 00:51 | advanced graphics capabilities at
their fingertips that native application
| | 00:55 | developers have had for years.
| | 00:57 | So if all that is enough to get you
excited, then let's get started with HTML5:
| | 01:01 | Graphics and Animation with Canvas.
| | Collapse this transcript |
| Using the exercise files| 00:00 | If you are a Premium member of the
lynda.com Online Training Library, or if
| | 00:05 | you're watching this tutorial on a
DVD-ROM, you have access to the exercise
| | 00:08 | files used throughout this course.
| | 00:11 | So let me show you how they're laid out.
| | 00:12 | Here we are in the Exercise Files folder.
| | 00:14 | The way I have laid it out is each
folder is named with a two-digit number at
| | 00:19 | the beginning, and that corresponds
to the chapter that we're currently
| | 00:22 | looking at in the course.
| | 00:24 | And the name that follows the number is
just a little hint of what's contained inside.
| | 00:29 | So if we open up one of these chapters,
you'll see that way I've laid out each
| | 00:33 | example file, there's two versions of each file:
| | 00:35 | there's a finished version
and there's a start version.
| | 00:37 | The finished version is the
particular tutorial in its finished state.
| | 00:42 | That's what I'll be showing at the
end of each one of the tutorials.
| | 00:45 | The start version is the same as the finished
version but with key pieces of code removed.
| | 00:50 | And what we'll do is any tutorial,
we'll start with the starting point, add the
| | 00:54 | code until we reach the same
point as the finished version.
| | 00:56 | So you really have your choice:
| | 00:58 | you can either open up the finished
version and see how things work and run it
| | 01:01 | for yourself, or you can follow along
with me as we build the start version
| | 01:05 | until it reaches the finishing point.
| | 01:08 | In addition to each one of the
tutorials, I've also included a file
| | 01:11 | called ExampleSnippets.
| | 01:13 | Let's go to the code editor
and see what that looks like.
| | 01:15 | This is the snippets file that
I've included for this course.
| | 01:17 | So each one of these chapters has
various code snippets that I add to the
| | 01:22 | starting point for each one of the tutorials.
| | 01:25 | This way, I just simply copy the code
and paste it into the starting point, so
| | 01:28 | you don't have to sit there and watch me type.
| | 01:30 | So I'll be doing things like copying
this piece of code, putting it into the
| | 01:34 | starting point, showing it
in the browser, and so on.
| | 01:37 | Now this ExampleSnippets file, you'll
have access to this as a free downloadable
| | 01:42 | tutorial file directly from the online
course page, even if you're not a Premium
| | 01:46 | member of the lynda.com Online Training Library.
| | 01:50 | If you are a Monthly subscriber or
Annual subscriber to lynda.com, you don't
| | 01:54 | have access to the exercise files, other than
that ExampleSnippets file that I just showed.
| | 01:58 | But you can follow along from
scratch with your own assets. All right!
| | 02:01 | Let's get started.
| | Collapse this transcript |
| Using the HTML5 Canvas element in the real world| 00:00 | Since the canvas tag is new to HTML5,
there are going to be browsers out there
| | 00:04 | that don't support it.
| | 00:05 | So let's take a quick look at what
happens when a browser that is not aware of
| | 00:09 | the canvas tag encounters one in a document.
| | 00:12 | So here we have a canvas,
and inside we have some text.
| | 00:17 | Now in browsers that understand what
the canvas tag is, this text will not show
| | 00:22 | up and will instead be replaced by the
canvas itself in the rendering surface.
| | 00:27 | A browser that does not understand the
canvas tag will ignore it and render the
| | 00:31 | contents of the interior
of the canvas tag instead.
| | 00:34 | In this case, let's just quickly
show you what I'm talking about.
| | 00:38 | What I'm going to do is simulate a
browser that does not understand canvas, since
| | 00:42 | all the browsers I have on
this machine know about it.
| | 00:44 | So I'll just quickly comment this out
and will comment this one out as well.
| | 00:52 | This is pretty much how the
browser will treat the canvas tag if it
| | 00:55 | doesn't recognize it.
| | 00:56 | So now let's just quickly take a look at that.
| | 00:58 | So you can see that in the case where a
browser doesn't know what the canvas tag
| | 01:04 | is, the interior text gets rendered instead.
| | 01:07 | So that will happen in cases where you
have an older browser and it comes across
| | 01:12 | a canvas tag, or generally speaking,
pretty much any tag it doesn't recognize.
| | 01:16 | But in the case where the browser
does understand what the canvas tag is--
| | 01:20 | let's go back and uncomment it,
save--and you can see that I've got a
| | 01:29 | style defined for this canvas up
here with a dotted 3-pixel black border
| | 01:33 | and a background color.
| | 01:34 | So it should render as a
gray square with a border.
| | 01:37 | Let's go back to the browser and refresh.
| | 01:40 | So I am going to refresh this now,
and you can see that in a browser that does
| | 01:43 | understand the canvas tag, it does
show up, and it's properly styled.
| | Collapse this transcript |
|
|
1. Examples of Current HTML5 SitesReal-world example: CanvasMol| 00:00 | Before we get into working with canvas
in the rest of the course, let's take a
| | 00:04 | look at some of the real-world examples
that people have built using canvas to
| | 00:10 | achieve effects and drawing operations
that used to require native plug-ins like
| | 00:15 | Silverlight and Flash but can now be
done using modern browsers and HTML5.
| | 00:20 | This example is called canvasMol.
| | 00:22 | It's on a web site called alteredqualia.com.
| | 00:25 | Basically, this shows how canvas can be
used to model molecules on a drawing surface.
| | 00:30 | So let's take a look at some ones.
| | 00:31 | Here's one of my
favorite ones; here's Caffeine.
| | 00:33 | So you can see that what's happening
here is when I click on a molecule over
| | 00:37 | here in this list, this canvas
drawing surface pops up and it shows me the
| | 00:41 | molecule for that particular item.
| | 00:44 | In this case, this is the caffeine molecule.
| | 00:46 | I can use the mouse to grab
this thing and move it around.
| | 00:50 | And I can choose some other ones.
| | 00:52 | Here's one, Fructose,
another one of my favorites.
| | 00:55 | So you can see now I bring up another
canvas, the frame rate slows down a little
| | 00:59 | bit because this drawing is happening
in real time, and the more canvases you
| | 01:04 | have on the drawing surface, the
more processing power it takes.
| | 01:08 | So let's add another one little one.
| | 01:09 | Let's add Lycopene, and then
we can scroll down and see that.
| | 01:13 | That's a pretty fairly complex
molecule, but you get the idea here.
| | 01:16 | What's happening is the canvas is
being used to render each one of these
| | 01:20 | molecular bonds with individual atoms.
| | 01:22 | You can see that they're all shaded
a certain way, and they're rotating.
| | 01:27 | Each one of the canvases responds to the mouse.
| | 01:31 | And we can add one more over here from the list.
| | 01:34 | Let's go ahead and add Penicillin.
| | 01:36 | So I can just go ahead and add each
one of these in succession, and what's
| | 01:39 | happening is a new little window is
being popped up with the canvas inside of it.
| | 01:44 | And you can see that each one of the
canvases is now drawing each molecule
| | 01:48 | rotating in real time.
| | 01:49 | Each one responds to the mouse.
| | 01:51 | You can see that as I add more
canvases, the drawing rate slows a little
| | 01:54 | bit, but not very much;
it's still highly usable.
| | 01:56 | Each one is still also pretty responsive.
| | 01:59 | So this is a really great example of
something that would've probably required a
| | 02:02 | plug-in in the past but is now just
happening natively using canvas in HTML5.
| | Collapse this transcript |
| Real-world example: Raphaƫl-JavaScript Library| 00:00 | So, canvas is used for a lot more
than just wizzy graphical effects.
| | 00:04 | This is the Raphael JavaScript library.
| | 00:07 | This is used for charting.
| | 00:08 | And it can create charts using both
canvas and a technology called SVG, which we
| | 00:13 | are not covering in this particular
title, but it can do both. So let's take a
| | 00:17 | look at what it does.
| | 00:18 | You can see down here,
I will just go down to the Demo section.
| | 00:20 | These are all examples of the kinds of
things you can do with the Rafael Drawing Library.
| | 00:26 | Let's take a look at this one right here.
| | 00:28 | This one shows example of a graph
that's showing data for particular months.
| | 00:32 | And you can see, as I switch among the
months, the chart is changing to show
| | 00:38 | various different data sets, and you
can see that there is a little animation
| | 00:42 | step that happens in there.
| | 00:43 | Let's go back to the first one.
| | 00:45 | Here is a really cool example called a
Polar Clock, and this is using canvas to
| | 00:50 | draw a clock that is drawn using circles.
| | 00:53 | So, you can see each one of these rings
is color-coded and the color-coded rings
| | 00:57 | correspond to the text up here.
| | 00:58 | So the blue ring is the
hours, the gray is the minutes.
| | 01:02 | You can see the second hand is out
here. Then the date is shown in the two
| | 01:06 | interior rings in different shades of green.
| | 01:08 | So, it is now April 26 and you can see
that this clock is just an interesting
| | 01:13 | way of using the canvas to draw
something that we take for granted every day,
| | 01:17 | such as clocks on the wall.
| | 01:18 | And let's take a look at one more example.
| | 01:20 | This here is an example of using the
canvas to rotate a pre-drawn image.
| | 01:26 | This is an actual JPEG image that's
drawn onto the canvas, and using these
| | 01:30 | controls, I can rotate it.
| | 01:32 | You can see that there is little
animation that goes along that as well.
| | 01:36 | You can see, it starts off slow,
speeds up, and then slows down, using easing.
| | 01:40 | These are all kind of things that used
to require plug-ins and are now provided to
| | 01:44 | you as part of canvas in HTML5.
| | Collapse this transcript |
| Real-world example: The Wilderness Downtown| 00:00 | A really great example of using HTML5
canvas to produce some really cool effects
| | 00:04 | is a site called thewildernessdowntown.com.
| | 00:08 | And this is a pretty immersive site
built by Arcade Fire and some other folks.
| | 00:14 | I am running this in Google Chrome.
| | 00:15 | It's actually pretty cool!
| | 00:17 | You type in the address of a place
and then the site builds a sort of
| | 00:23 | customized music video around the
location you give it, complete with some
| | 00:28 | interesting HTML5 canvas effects.
| | 00:30 | You can see the birds are being
chased away by my mouse over here.
| | 00:33 | That's actually pretty cool.
| | 00:34 | All this is HTML5 that you are seeing right now.
| | 00:36 | So, let's give it an address, and I'm
going to use the address of lynda.com's
| | 00:45 | recording studio, and we are here
in beautiful Ventura, California.
| | 00:50 | I am going to click Search.
| | 00:51 | Okay, so now it's going to
go build out that music video.
| | 00:55 | Right, we are ready to go,
so we can play the film.
| | 00:57 | So, now as you're watching the movie, I
am going to point out some of the canvas
| | 01:01 | effects that are happening.
| | 01:02 | (music playing)
First, you see the video come up.
| | 01:06 | (video playing)
| | 01:13 | This is being accomplished right
now via HTML5 video.
| | 01:16 | (video playing)
| | 01:34 | So, now here is an example of the
canvas being used to draw the birds flying
| | 01:40 | around the sky up there,
those guys right here.
| | 01:44 | You can see they are still
responding to my mouse. (video playing)
| | 01:47 | (video playing)
| | 02:04 | So, now here is the combination.
| | 02:06 | We have a video that's using an image
that's been pulled from the Google Earth service.
| | 02:12 | Those birds you see being drawn there
are drawn using HTML5 canvas and you can
| | 02:19 | see that there are various windows
coming and going.
| | 02:28 | This is the HTML5 canvas
being used to render an image.
| | 02:32 | You saw it there, and it was
faded out a little bit to make it look
| | 02:34 | like it was a bit old.
| | 02:35 | You can see the effect over there.
| | 02:39 | So, the colors have been sort of washed
out a little bit using the canvas effects.
| | 02:42 | (video playing)
| | 02:54 | You can see the image is now being rotated.
| | 02:57 | There is some more canvas with our location.
| | 03:08 | You can see that as he's
turning around the video down there,
| | 03:10 | it is synchronized with the video up top.
| | 03:12 | (video playing)
| | 03:38 | That's pretty much it.
That's a pretty great use of canvas.
| | 03:42 | You can see here that at the end it
gives you an opportunity to write a little
| | 03:45 | postcard to yourself and the contents
here are drawn using HTML5 canvas, really
| | 03:51 | great example of using canvas
technologies to augment existing media, like video
| | 03:56 | and audio and different windows, and
just a nice immersive experience.
| | Collapse this transcript |
| Real-world example: Sketchpad| 00:00 | Another really great example of using
HTML5 canvas to accomplish things that
| | 00:04 | used to require native
applications is Sketchpad.
| | 00:08 | And you can see the URL up
there is mugtug.com/sketchpad.
| | 00:12 | This is a drawing application created
using HTML5 canvas, and I'm going to just
| | 00:17 | do some stuff, like I can select the
ellipse, and I can draw the ellipse on the
| | 00:21 | canvas here, and I can use the
brush and I can draw things.
| | 00:25 | And you can see that I've got
various settings in these windows down here.
| | 00:28 | So, I can change all kinds of
things. I can change colors.
| | 00:37 | I can even do advanced operations like cropping.
| | 00:39 | So, this is a cropping tool.
| | 00:41 | I am going to drag out a little
cropping rectangle here and hit Enter, and you can
| | 00:47 | see that by using the canvas, I'm able
to grab subsets of images that have been
| | 00:51 | drawn, draw them in to entirely new canvases.
| | 00:55 | This is actually a really powerful application.
| | 00:57 | You can see also up here I have
other windows I can drag out. So this is a
| | 01:00 | great example of something that used to
require a native application to do and
| | 01:05 | it's been implemented entirely
using canvas and HTML5 technologies.
| | Collapse this transcript |
| Real-world example: Pirates Love Daisies| 00:00 | Okay, the next example we are going
to look at is Pirates Love Daisies.
| | 00:03 | Pirates Love Daisies is a game that
was produced using just HTML5 canvas and
| | 00:10 | native web technologies.
| | 00:12 | You've probably seen games like this before.
| | 00:13 | It's a classic tower defense game where
you have to defend something against a
| | 00:18 | wave of oncoming bad guys, probably
something along the lines of Plants Versus
| | 00:23 | Zombies is a pretty famous one.
| | 00:25 | In this case, you are the pirates, and
there's a group of mean sea creatures that
| | 00:29 | are trying to come and steal your
daisies, and that's the premise of the game.
| | 00:32 | So, I am just going to go
ahead and click start the game.
| | 00:34 | And all this is done using canvas, so I
am just going to go and click a map, and
| | 00:38 | I am going to click Play.
| | 00:38 | So, now down here on my people, I am
going to click on a pirate and I am going
| | 00:43 | to choose an anchor point to put them.
| | 00:45 | And so you can see that there's my
pirate. I am going to go ahead and upgrade
| | 00:49 | Scarlett and Scarlett is going to make
quick work of the rats that are coming in to
| | 00:53 | try and take my daisies.
Maybe I'll put Inigo up there.
| | 00:59 | You can see that this
game, it's pretty advanced.
| | 01:01 | It was created using a JavaScript
library called Easel, like an artist
| | 01:04 | drawing easel, Easel.js.
| | 01:07 | And it's a pretty great little game.
| | 01:09 | The pirates are defending the daisies up here.
| | 01:11 | This is just implemented using canvas.
| | 01:13 | This is HTML5 canvas
using native web technologies.
| | 01:16 | There's no Silverlight here.
| | 01:18 | There is no Flash involved, and it's
a pretty good example of what you can
| | 01:21 | do using canvas.
| | Collapse this transcript |
|
|
2. Setting Up Your WorkspaceInstalling the tools| 00:00 | Before we can begin working with the
HTML5 canvas, we first have to make sure
| | 00:04 | that we have the right tools installed.
| | 00:07 | You're going to need to have some
browsers installed to test with, and you can
| | 00:10 | see over here I've got Firefox,
and Chrome, IE, Opera, and Safari.
| | 00:16 | You can get those browsers from
their respective browser download pages.
| | 00:21 | Make sure you have IE of at least
version 9, because that's the version of IE
| | 00:25 | that supports the canvas tag. And in
addition to the browsers that you are going
| | 00:29 | to need to test out your results in, you
will need to have a text editor to edit
| | 00:34 | the HTML and JavaScript code
that we'll be working with.
| | 00:38 | Now you can use any code editor you want to--
| | 00:41 | You probably already have your
favorite code editor for your platform.
| | 00:44 | However, I'm going to be using a
product called Aptana Studio in this course,
| | 00:50 | and this is the web site
where you can download it from.
| | 00:52 | If you just go to aptana.com, you'll
see that there's a products link, and
| | 00:57 | that's this right here.
| | 00:58 | You can download Aptana Studio.
| | 01:00 | The reason I'm using Aptana
Studio is because it is cross-platform--
| | 01:04 | it works on both Mac and Windows--and it's free.
| | 01:08 | So again, you can use
whatever code editor you want.
| | 01:11 | I just happened to be using Aptana, and
once you've downloaded and installed it,
| | 01:15 | this is what it looks like.
| | 01:16 | No big surprises here.
| | 01:18 | It pretty much works the
same way as any other IDE does.
| | 01:21 | So once you have your browsers
and code editor installed, we can go ahead and
| | 01:25 | get started learning how
to use the HTML5 canvas.
| | Collapse this transcript |
| Exploring the Canvas examples used in this course| 00:00 | The HTML5 canvas provides a lot of
drawing operations to learn about.
| | 00:04 | So what I'm going to do first is show
you a quick overview of the kinds of
| | 00:08 | things that we're going to
learn how to do in this course.
| | 00:11 | So using HTML5 canvas, we'll learn about
how to draw lines, and you can see this
| | 00:15 | is the example here.
| | 00:16 | This is the actual finished example
that we're going to build. And you can see
| | 00:20 | that we can draw lines of varying
thickness with different end caps and
| | 00:23 | different kinds of joins.
| | 00:25 | We'll see how to draw arcs. And again,
these are the finished examples that
| | 00:28 | you're going to be able to build when
you've watched that particular section.
| | 00:32 | So here we do have some arcs.
Some of them are filled.
| | 00:36 | We can draw text in the
canvas using various effects.
| | 00:39 | We've got some colors, and sizes,
and stroking and filling going on, We'll see
| | 00:43 | how to do things like draw shadows, so
these are objects that have shadows with them.
| | 00:49 | You can see that the shadow color and
blur effect can be changed depending on
| | 00:53 | the type of object that you're drawing.
| | 00:55 | We'll also see how to do things like
draw gradients, both linear gradients, as
| | 01:00 | in this example, and radial gradients.
| | 01:02 | Then we'll move on to some more
advanced stuff, like seeing how the canvas can
| | 01:06 | draw using different compositing methods.
| | 01:09 | These compositing methods affect how
objects are drawn to the canvas, and there
| | 01:13 | are twelve of them and you can see
the examples here. And again, you'll be
| | 01:16 | building this later on in the title.
| | 01:17 | Then we will see how to use things like
transformations to move objects around
| | 01:22 | on the canvas and affect how they are drawn.
| | 01:25 | And you can do things like
rotate and scale and translate.
| | 01:28 | This is the rotate one.
| | 01:29 | We'll see how to do this later.
| | 01:30 | Then we move on to some
more advanced operations.
| | 01:33 | I'll show you how to build
animations like this one, where we have a box
| | 01:37 | moving across a blue canvas, and we'll build
something a little more advanced than that even.
| | 01:42 | We'll build a nice little slideshow rotator.
| | 01:45 | You can see that this is rotating through
some pictures that are being drawn to a canvas.
| | 01:50 | So these are the examples that we're
going to be building, and you might want
| | 01:54 | to fire up your code editor, because
we're going to just dive right in and
| | 01:57 | start building stuff.
| | Collapse this transcript |
|
|
3. Introducing the Canvas ElementIntroducing the Canvas tag| 00:00 | Let's begin by introducing the canvas element.
| | 00:03 | The canvas element provides web pages
with a place where they can draw free-
| | 00:07 | form graphics of all kinds: shapes,
images, text, lines, all kinds of objects.
| | 00:13 | Just think if it as a piece of paper
on the page where your script code can
| | 00:16 | just draw anything it wants.
| | 00:18 | The canvas tag is supported in all of the
latest browsers, and I have listed them here.
| | 00:23 | So as long as you have a modern
version of that particular browser, it should
| | 00:27 | support the canvas tag.
| | 00:29 | Now, browsers that don't support
canvas can display fallback content.
| | 00:33 | So if you have a browser that doesn't
understand what a canvas is, you can place
| | 00:37 | content inside the canvas tag that
will be displayed to the user when their
| | 00:41 | browser tries to render it.
| | 00:42 | Pages can actually have more than one
canvas and in fact, you can even overlap them.
| | 00:46 | One of reasons why you might do this is
because canvases can be set to be transparent.
| | 00:51 | So you might have one canvas that
contains say the background for a game and another
| | 00:55 | canvas that has the characters in the
game and so on and so forth, and you can
| | 00:59 | position them on top of each other.
| | 01:01 | So you can have more than one
canvas, and it might come in handy to have
| | 01:03 | more than one canvas.
| | 01:04 | Now it's important to know that canvas
contents are created on the fly using script.
| | 01:10 | Now what this means is once you've
drawn stuff onto the canvas, there is no
| | 01:14 | going back to get it again; it
doesn't become part of the page DOM.
| | 01:17 | So the bits are on the screen, and if
you want to remember them, you have to
| | 01:21 | care of it yourself.
| | 01:22 | Once they're drawn, they are just
forgotten about by the script engine.
| | 01:25 | They're good for dynamic visual media,
but the canvas is not good for things
| | 01:30 | that you might want to manipulate
later using script, and that's what SVG is
| | 01:35 | for, and we'll take a little
bit of a peek at that later.
| | 01:37 | Let's take a look at the canvas tag.
| | 01:39 | The canvas coordinate system starts at
the upper left, and it has two axes with
| | 01:45 | increasing values of X going from the
left to the right and the Y axis going
| | 01:48 | from top to the bottom.
| | 01:50 | All canvas element start out
invisible, and that means that they are a
| | 01:53 | transparent black background.
| | 01:55 | So, there is the black canvas with
the opacity set all the way down to 0,
| | 01:59 | so they can't be seen.
| | 02:00 | This graphic shows you what
the coordinate system looks like.
| | 02:03 | So on the left-hand side there we have the Y
axis, increasing in values from top to bottom.
| | 02:08 | We have the X axis going from left to
right, and we have 0, 0 point up there in
| | 02:12 | the corner, and the width and
height down on the lower right.
| | 02:16 | The canvas tag is declared using the
word 'canvas', and you typically provide it
| | 02:20 | with an ID, because you'll be accessing
it from script, and a width and a height.
| | 02:24 | And that Fallback content you see
there inside the canvas tag is what will be
| | 02:28 | displayed to the user if a browser
does not understand what a canvas is.
| | 02:33 | Canvases come along with some attributes
and functions as well, and here they are.
| | 02:38 | There is a width and a height, which
defined the width and the height of the
| | 02:41 | canvas, and there is a couple of methods.
| | 02:43 | There is toDataURL and the getContext.
| | 02:46 | So let's take a look at each one of those.
| | 02:48 | The width and the height
properties are pretty much self-explanatory.
| | 02:51 | They are the width and the height of
the canvas, and if you don't define them,
| | 02:55 | they default to 300 wide by 150 height.
| | 02:58 | And it's important to note that, as
well as getting the values of these
| | 03:02 | properties, they can be set.
| | 03:04 | So you can dynamically change the width
and the height of the canvas from your code.
| | 03:09 | The toDataURL method takes the contents
of the canvas and makes a static image
| | 03:14 | out of them as a data URL.
| | 03:17 | Now to do this, you pass in the type of
image you want the toDataURL method to
| | 03:22 | create, such as image/png, and that
support is mandatory according to the W3C
| | 03:28 | spec. But some browsers may choose to
support other formats like image/jpeg, or
| | 03:34 | image/gif that kind of thing.
| | 03:36 | So this method basically takes the
contents and gives you back a Base64 encoded
| | 03:41 | data URL of the contents.
| | 03:44 | The getContext method is
probably the more important ones.
| | 03:47 | It retrieves the drawing context for
the canvas, and the drawing context
| | 03:52 | contains information about the canvas and
provides all of the methods you use to draw with.
| | 03:58 | Things for setting colors and stroke
styles and drawing shapes and so on, all of
| | 04:03 | that is done using the context.
| | 04:06 | So, let's actually switch over to our
code editor and build our first canvas.
| | 04:10 | Okay, so here I am in Aptana Studio
and I'm going to open up the example files.
| | 04:16 | So if you go into the Exercise Files
folder, I'm going to go into the folder for
| | 04:20 | this lesson and open up the start.
This is our Firstcanvas_start.html.
| | 04:27 | I'm also going to open up my
snippets file, and I'll be referring to this
| | 04:33 | throughout this course.
| | 04:34 | Essentially, this file contains all
the code snippets for each one of the
| | 04:38 | examples in order to go from the
start state to the finished state, and I'm
| | 04:41 | going to use these so that you
guys don't have to watch me type.
| | 04:44 | And if you have access to this file, you can
follow along with me in your own code editor.
| | 04:48 | So what we're going to first do
is put a canvas into this document.
| | 04:51 | I am going to put it right here in the body.
| | 04:53 | So I'll go to the Snippets, and I'll take this
canvas and I'll paste it in. So let's save.
| | 05:00 | So here is the canvas tag, here's it's ID,
and I've got a width and a height on there.
| | 05:05 | And here is the fallback content right there.
| | 05:08 | It just says, "Your
browser does not support canvas."
| | 05:10 | All right, let's take a
look at this in the browser.
| | 05:14 | So we'll go out here.
| | 05:15 | I am going to double-click, and
you can see that nothing shows up.
| | 05:18 | Remember, I said that
canvases all start out as invisible.
| | 05:22 | So we need to do something
to make this canvas visible.
| | 05:24 | Let's go back into the code.
| | 05:25 | I am going to go back to my
snippets and I'm going to copy this style
| | 05:29 | declaration right here.
| | 05:30 | And just like other HTML elements, you
can define styles that affect canvas tags.
| | 05:37 | So I am going to copy this and go back to my
source and paste that here in the head section.
| | 05:44 | So I've defined a style
for the canvas with this ID--
| | 05:48 | that's this guy right here--and it has
a border which is a dotted 3-pixel black
| | 05:54 | outline and a light gray background-color.
| | 05:57 | So let's save, and let's go back
to the browser, and let's refresh.
| | 06:01 | Okay, now you can see that the canvas is
visible, so it has a dotted border here,
| | 06:07 | and the background is light gray.
| | 06:09 | So let's see how this looks in
another browser. This is IE.
| | 06:14 | Let's open this up in Firefox,
and you can see it looks the same.
| | 06:19 | Now we know how to declare a canvas tag.
| | 06:21 | We know how to style it and make it visible.
| | 06:23 | Let's take a look at how canvas
compares to SVG, and then we'll move in to
| | 06:28 | some actual drawing.
| | Collapse this transcript |
| Understanding the differences between Canvas and SVG| 00:00 | Let's take a look at how canvas
compares to SVG, or Scalable Vector Graphics.
| | 00:05 | SVG is another way of
drawing content into web pages.
| | 00:10 | It's similar to the canvas, but it
works in a pretty different fashion.
| | 00:14 | So let's compare the two.
| | 00:16 | Canvas has elements that
are drawn programmatically.
| | 00:20 | In other words, your script code draws
elements directly onto the canvas surface.
| | 00:25 | In SVG, the elements are actually a part
of the page's DOM, or Document Object Model.
| | 00:32 | In SVG, when you have a shape, say a
rectangle or an arc or some kind of
| | 00:36 | curve, that's actually a
tag that is in the document.
| | 00:40 | Your script can refer to it in the DOM.
| | 00:42 | You can manipulate it.
| | 00:43 | You can't do that in canvas.
| | 00:44 | Once something is drawn to the canvas,
the browser forgets all about it.
| | 00:48 | It just puts the bits onto the canvas
and then moves on to the next operation.
| | 00:52 | In canvas, drawing is done with pixels,
whereas in SVG drawing is all done with vectors.
| | 00:59 | Vectors are lines that are determined
by start points and end points and curves,
| | 01:04 | and on the canvas that's how you do it.
| | 01:06 | You actually put pixels
directly onto the canvas surface.
| | 01:09 | Canvas does not have animations
built into it, whereas SVG does.
| | 01:15 | In the canvas, when you want to
create animations, you have to do that
| | 01:18 | using script and timing mechanisms, which we
will see how to do later on in this course.
| | 01:23 | In SVG, basic animations, such as moving
objects around, all that stuff is built in.
| | 01:28 | Canvas is pretty high performance for
pixel-based drawing operations, whereas
| | 01:34 | SVG is based on a standard XML syntax.
| | 01:38 | So where canvas gets a little bit
better performance because it can take
| | 01:40 | advantage directly of your
computer's hardware accelerated GPU, or
| | 01:45 | Graphics Processing Unit,
| | 01:46 | SVG uses XML which might be a little
bit slower to process, but it provides
| | 01:51 | better accessibility, because again, the
elements of the drawing are part of the DOM.
| | 01:57 | So this is a pretty complete basic look
at how the two are different, but keep
| | 02:03 | in mind they're not mutually exclusive.
| | 02:05 | You can use canvas and SVG in the same web page.
| | 02:09 | And because you can position elements,
you might even find a way to use the two
| | 02:13 | of them together, have a canvas
in the background and SVG on top.
| | 02:17 | Now what you can't do is draw SVG
into a canvas or vice versa, but just
| | 02:23 | remember, they're not mutually exclusive.
| | 02:25 | You can actually use both.
| | Collapse this transcript |
|
|
4. Understanding the Canvas Element and 2D Drawing APIIdentifying the Canvas element's methods and properties| 00:00 | We've seen how to
declaratively create a canvas in HTML.
| | 00:04 | In this example, let's see how we can use
script to affect how canvas looks on the browser.
| | 00:10 | So I'm going to open up my example
file, and in my exercise files, and I'm in
| | 00:15 | chapter 04, and we'll open up
contextprops_start, and you can see we've got some
| | 00:20 | code we need to write.
| | 00:21 | Let's go and take a look at
this in the browser really quick.
| | 00:24 | So I'll bring this up in IE,
and you can see there's a dotted outline.
| | 00:29 | There is no background color here,
just the outline, and what we're going to
| | 00:32 | do is write some code that will affect how the
canvas tag itself is displayed in the browser.
| | 00:38 | So let's go back to the code and over
in my snippets, I'm going to copy the
| | 00:43 | three lines under the ContextProps
section, so we'll copy those and we'll put
| | 00:48 | them in here, in the window.onload function.
| | 00:52 | So what we're doing here is when the
window loads, we've got some code that's
| | 00:56 | going to get a reference to the canvas
element by calling getElementById, and
| | 00:59 | that's thus canvas right here.
| | 01:01 | And then we're going to
programmatically change the width and height from 400
| | 01:05 | and 300, which are the defaults, down to
150 x 150. So we save this and then when we
| | 01:12 | go back to the browser. Now when I
refresh this, you can see that the canvas got
| | 01:18 | a little bit smaller.
| | 01:20 | So this shows us how we can
programmatically display the canvas using different
| | 01:25 | properties, just the same way
that we can do it from HTML.
| | 01:28 | Now in HTML, we can give it attributes
that affect how the canvas is displayed
| | 01:32 | initially, but once that height and
width is defined in HTML, we can still go
| | 01:37 | back and code and programmatically affect them.
| | Collapse this transcript |
| Using the Canvas drawing context| 00:00 | To actually draw things onto the canvas,
we need to use the canvas's 2D drawing
| | 00:05 | API and to do that, let's
take a look at how it works.
| | 00:09 | Now drawing on a canvas
requires a series of steps.
| | 00:13 | And in step one, we need to retrieve a
reference to the canvas; in other words,
| | 00:17 | we have to actually get the
canvas element out of the page.
| | 00:20 | Once we've got a reference to the
canvas element, we get the drawing
| | 00:24 | context from it using the
getContext () method that we talked about a
| | 00:28 | little bit earlier.
| | 00:30 | Now if the result of the getContext ()
call is not null, then you know you have
| | 00:35 | the drawing API and you can
go ahead and start using it.
| | 00:38 | Now to do this in script, let's
imagine we have the following example.
| | 00:41 | We've the canvas tag that's defined.
| | 00:44 | This is the same way we've been
defining our canvas tags up until now.
| | 00:46 | We've got an ID, width, height, and some fallback
content. So to draw in script, this is how it goes.
| | 00:52 | Typically, you would do
something like define a function.
| | 00:55 | You would call
getElementById to get the canvas element.
| | 00:59 | Once you've got the canvas element, you
then ask for its context. So here we are
| | 01:03 | saying canvas element.getContext, and
we're passing in 2D, because we want the 2D
| | 01:08 | drawing API. And if that result is not
equal to null, then we can go ahead and
| | 01:14 | draw, and then you close
the function and off you go.
| | 01:18 | So the canvas drawing API in
2D is pretty comprehensive.
| | 01:22 | It's broken up into three groups.
| | 01:23 | The first group has to do with shapes.
| | 01:25 | There are rectangles, lines,
arcs, paths, colors, and styles.
| | 01:30 | There are different kinds of curves,
such as Bezier and Quadratic, and
| | 01:33 | then there is text.
| | 01:34 | The next group has to do
with how things are drawn.
| | 01:37 | There are various compositing
properties we can use, patterns and gradients.
| | 01:41 | You can create shadows.
| | 01:42 | You can also create clipping paths,
and we'll investigate all of these later.
| | 01:46 | And then finally there are things like
transforms, images and video, and you
| | 01:49 | can even access the raw pixels of
the canvas in order to do some pretty
| | 01:54 | interesting effects. And throughout the rest of
this course, we'll see how to do each one of these.
| | 01:58 | So let's take a really
simple example to begin with.
| | 02:00 | Let's actually draw on the
canvas using the 2D drawing API.
| | 02:04 | So I'm over here back in my code
editor again, and I'm going to open up my
| | 02:08 | example. And in this case, I'm going to
use the contextdraw_start example, under
| | 02:14 | chapter 04, so I open that.
| | 02:16 | So here is our file.
| | 02:17 | There is our canvas.
| | 02:18 | Here is the code we're going to write.
| | 02:20 | I can go copy these lines from the
snippets under ContextDraw. So I'll copy,
| | 02:27 | and we'll go back to the source
code and we'll paste it in here.
| | 02:31 | So what we're going to do now is use
the 2D drawing API to put that light gray
| | 02:36 | background that we saw earlier into the canvas.
| | 02:41 | Now, I don't expect you to
necessarily understand all this right away.
| | 02:44 | It's just a simple example
to show you how this works.
| | 02:46 | So first, we get a reference to
the canvas element by calling
| | 02:49 | getElementById canvas. Then we say
hey, do we have the canvas object, and
| | 02:54 | is there a method named getContext?
| | 02:56 | And if there is, we then call the
getContext method using 2D as the argument.
| | 03:02 | That gets us the 2D drawing API.
| | 03:04 | And then finally, if all that was
successful, on the context, we say set the
| | 03:09 | fill style to be light gray, and then
we're going to call a function called
| | 03:12 | fillRect and fillRect
takes a couple of arguments.
| | 03:15 | There is the origin to start drawing at,
0,0, and then the width and height of the
| | 03:20 | rectangle you want to draw--in this
case, the width and height of the canvas.
| | 03:24 | So you've probably
guessed by now what this does.
| | 03:26 | It's going to fill the entire
canvas with a light gray background.
| | 03:30 | So let's go ahead and save.
| | 03:32 | All right, let's go over to the browser.
| | 03:34 | So I am going to bring this up in
the browser, and you can see that's
| | 03:37 | exactly what happens.
| | 03:38 | So now the canvas has been filled in.
| | 03:40 | Let's go ahead and view this in another
browser to make sure it is working correctly.
| | 03:43 | I'll open this in Firefox,
and there is the same result.
| | 03:48 | So that's a pretty simple example
of using the 2D drawing API to fill a
| | 03:52 | rectangle with a gray color,
but it gets a lot better than that.
| | Collapse this transcript |
|
|
5. Basic Canvas Drawing TechniquesSetting and using colors and styles| 00:00 | One of the most basic things that you
need to set when you're going to draw on
| | 00:03 | the canvas is usually involving some
kind of color and style, and the canvas
| | 00:08 | 2D drawing context provides some
global properties that affect how objects are
| | 00:14 | stroked and filled.
| | 00:15 | And there are three properties.
The first is the fillStyle.
| | 00:19 | That's the style to use when filling a
shape. And you can set this to anything
| | 00:22 | that you would normally
set a CSS color property to.
| | 00:26 | So, for example, you can use a CSS
color or a gradient or a pattern, and this
| | 00:31 | defaults to black if you don't set it.
| | 00:34 | We'll take a look at
gradients and patterns later.
| | 00:35 | We'll focus on colors for now.
| | 00:37 | In addition to the fillStyle, there is a
strokeStyle. And again this is the same idea.
| | 00:41 | You can set this to a color or
gradient or a pattern, and also defaults to
| | 00:45 | black, and this is the color or style
that's you used when strokes are drawn,
| | 00:50 | usually lines or outlines on objects
that have an area. And then there is the
| | 00:56 | lineWidth property, and this is the width of
the imaginary pen that the canvas uses
| | 01:02 | when it's drawing lines. And that defaults to
a width of one, but you can set to anything.
| | 01:08 | There is two-step process
involved to draw with colors and styles.
| | 01:12 | Step one is you set the fill and stroke
styles and the line width to whatever values
| | 01:18 | you want, and then you call a
drawing operation that creates some shape,
| | 01:23 | or does some kind of drawing thing.
| | 01:25 | So let's take a look at that
in code and see how it works.
| | 01:28 | Okay, so here I am in my editor, and I'm
going to start off with my example
| | 01:33 | colors_start.htm file.
| | 01:37 | If we look at this in the browser really quick,
| | 01:39 | you can see here is our canvas,
and I've outlined it so we can see it.
| | 01:43 | So, let's go back now to the code.
| | 01:46 | Now in my Snippets under the Color
section, I'm going to first copy these two
| | 01:51 | lines and paste them into here.
| | 01:55 | So we go through all the operations to
get our drawing context to make sure that
| | 01:58 | we have a valid canvas and everything,
and then I set the fillStyle to be
| | 02:02 | green. And then I call an operation
called fillRect and that's going to fill
| | 02:06 | the rectangle with this color. So let's
go back to the browser and refresh, and
| | 02:12 | you can see that, sure enough, a
green rectangle shows up on the canvas.
| | 02:15 | Now let's use the strokestyle, so
back in my Snippets, I'm going to copy the
| | 02:19 | next three lines, copy, back to the
code, and we'll paste those in here.
| | 02:27 | So in this example, now I'm setting the
lineWidth to be five and in the
| | 02:32 | strokeStyle I'm going to use the CSS style
declaration of RGB and Alpha. And I'm going
| | 02:39 | to set the color to be 100% opacity of
blue. And this time I'm going to use the
| | 02:45 | strokeRect function, and this
will actually fill the rectangle.
| | 02:48 | This has put a line around the edge.
So we save. When we go back to the browser,
| | 02:53 | we refresh, and now you can see that we have a
green rectangle with a blue outline around it.
| | 03:00 | So what we've done here is demonstrate
some basic drawing operations on how to
| | 03:03 | set the filling and stroking style, along
with the width of the pen, to affect how
| | 03:09 | things are drawn onto the canvas,
And these kinds of properties will affect lots
| | 03:13 | of different things that you draw on the canvas,
| | 03:15 | so this is a pretty basic
thing to learn how to do.
| | Collapse this transcript |
| Drawing basic shapes: Rectangles and lines| 00:00 | In this movie, we were going to
see how to draw some basic shapes.
| | 00:04 | Now we've already seen these couple of
times in other examples, but let's take a
| | 00:08 | deeper look at how
rectangles and lines are drawn.
| | 00:12 | Now, rectangles are the only primitive
shapes supported by canvas. Unlike, say
| | 00:16 | another technology like SVG
that also supports the ellipse,
| | 00:20 | the canvas only has the rectangle
as what is called a primitive shape.
| | 00:25 | It's a shape that's very simple to
draw and it only requires one routine.
| | 00:29 | Rectangles are pretty much the only
primitive one supported by canvas.
| | 00:33 | There are three functions
for operating rectangles.
| | 00:36 | The first one is the clearRect function,
which erases the rectangle defined by
| | 00:42 | the parameters you give it.
| | 00:43 | In other words, it makes
the area fully transparent;
| | 00:45 | it gets rid of the contents of that rectangle.
| | 00:48 | The other two are strokeRect and fillRect.
| | 00:51 | strokeRect outlines a rectangle with
whatever the current stroke style is, and
| | 00:55 | fillRect fills the rectangle with
whatever the current fill style is.
| | 00:58 | Now all three of these rectangle-drawing
operations take a starting point of the
| | 01:03 | upper-left corner of the rectangle that
you want to draw--that's the point where
| | 01:06 | the rectangle will start--
and then a width and a height.
| | 01:08 | It makes a rectangle as wide as
you say and as high as you say.
| | 01:12 | Unlike other drawing systems where
you give it all four points, here all
| | 01:16 | you need to do is specify one point
and then how high and how wide you want
| | 01:21 | the rectangle to be.
| | 01:22 | Lines are a little bit different.
| | 01:24 | Lines can be created using a variety of
settings for how lines join together and how they end.
| | 01:31 | So let's take a quick
look at the line operations.
| | 01:35 | The first two functions, moveTo and
lineTo, are used to get ready to draw a line.
| | 01:41 | So the moveTo function moves the
imaginary pen to the given point, but it
| | 01:45 | doesn't actually draw anything.
| | 01:46 | Imagine you are picking you are picking
the pen up from the paper and moving it
| | 01:49 | to its new location.
| | 01:51 | The lineTo actually does draw a line
from whatever the current pen point is to
| | 01:56 | the new point that you give it.
| | 01:58 | The next three properties, lineWidth,
lineCap, and lineJoin, determine how the
| | 02:03 | line looks on the screen.
| | 02:05 | So we have already seen the lineWidth
before. That determines how wide the line is.
| | 02:09 | The lineCap defines how the ending of
line is drawn, and there's three properties.
| | 02:13 | There is the butt property, which is
default, or you can draw lines with round
| | 02:17 | ends or square ends.
| | 02:19 | The lineJoin property determines how
lines join together when you do multiple
| | 02:23 | line tos, making the join as a round
join, a bevel join, or a miter join,
| | 02:28 | which is the default.
| | 02:30 | The miter limit is related to the miter
join, and this the limit at which line
| | 02:34 | joins are cut off and are drawn as
bevels. And that defaults to 10, and we'll
| | 02:40 | see that in a moment.
| | 02:41 | The beginPath begins a new set of
drawing operations, and the stroke function
| | 02:47 | collects all the current path
commands and then draws them.
| | 02:50 | So we will see how to do that in a moment.
| | 02:52 | But first, let's get started
drawing some basic rectangles.
| | 02:56 | So in my snippets, I'm under the
Rectangles section, and I am going to open up my
| | 03:01 | file called rectangles_start. And here
is where I am going to paste my code in.
| | 03:07 | So I am going to go back to the
snippets, and I am going to take the first two
| | 03:12 | sets and I am going to
copy that and paste it in.
| | 03:18 | So in this case, we are going to draw
first a stroked rectangle, and it has a blue
| | 03:22 | line that is five pixels wide, and then
we are going to draw a fill rectangle.
| | 03:26 | So let's save and go to the browser.
| | 03:29 | Okay, so you can see there
is the operations right there.
| | 03:32 | There's the stroked one.
There is the filled one.
| | 03:34 | Let's go back to the code.
| | 03:36 | So now I'll copy and paste the other two.
| | 03:38 | Actually, I'll do this one first.
| | 03:43 | I'll copy that. We'll paste it in.
| | 03:46 | In this case, we have a rectangle
that's both stroked and filled.
| | 03:49 | So the stroke will be red
and the fill will be yellow.
| | 03:52 | Then we have increased the lineWidth to 10.
| | 03:55 | So we've set the new properties, and then we draw.
| | 03:57 | So we fill and stroked the rect, so
let's save and refresh the browser.
| | 04:02 | You can see that now you got three
rectangles, different kinds of properties.
| | 04:07 | And then lastly, let's clear a rectangle.
| | 04:11 | So I am going to copy and we'll paste.
| | 04:13 | So here is what we are going to do.
| | 04:14 | We are going to create a rectangle
that cuts across all three of the
| | 04:19 | rectangles we drew previously.
| | 04:21 | So you can see that this rectangle
starts at the 25, 25 point, near the
| | 04:24 | upper left, and has a width
of 100 and a height of 125.
| | 04:29 | In fact, they all have
the same height and width.
| | 04:32 | They just happen to start at different
X points so that they move further and
| | 04:35 | further to the right along the canvas.
| | 04:38 | And then the clear rectangle is
going to start at the X of 15,
| | 04:42 | so before the first rectangle. And the Y
point of 75, and it is going to be
| | 04:47 | 450 pixels wide and 50 pixels high.
| | 04:50 | So let's save this and see what it does.
| | 04:53 | So when we refresh, see all three
rectangles got drawn, but then a rectangle
| | 04:58 | right here got cleared out from underneath them.
| | 05:01 | So that's how you can clear a rectangle.
| | 05:04 | Let's now take a look at the lines.
| | 05:06 | So I am going to go back to my example
file. I'm going to open lines_start now.
| | 05:13 | So here is the starting point.
| | 05:15 | Let's go back to the snippets.
| | 05:16 | So now let's go up to the lines section,
which is right there, and we've got
| | 05:22 | varying examples that we are going to do.
| | 05:24 | So the first example, we will
copy these lines right here.
| | 05:28 | We'll copy and we'll paste.
Let's review with these do.
| | 05:34 | So what we are doing here is creating a
for loop that goes from 0 to 10, and we
| | 05:39 | are going to draw lines of varying widths.
| | 05:42 | Now, to draw a line, the way that you
do this is you always begin a drawing
| | 05:45 | operation with the beginPath
function. That tells the canvas that a path
| | 05:49 | operation, which lines are
part of, are about to begin.
| | 05:53 | So then we set that lineWidth.
| | 05:54 | In this case, we are going to set the lineWidth to
whatever the loop counter is +1 pixel.
| | 05:59 | So it will start off at 1 and end at 11.
| | 06:02 | And then we are going to move to the X
position here and the Y position defined
| | 06:08 | by the current line that we were drawing.
| | 06:10 | And then we are going to draw a line to
the X position of 475 and the same Y.
| | 06:16 | So this will draw 10 lines of varying widths,
and after each line is drawn, we call stroke.
| | 06:22 | That actually fills the line in.
| | 06:23 | So the process is called beginPath.
Do your line operations. Then call
| | 06:27 | stroke, and that will stroke
the lines, so let's do that.
| | 06:30 | We are going to save, and then
we are going to go to the browser.
| | 06:33 | You can see in the first
example that's what's happened.
| | 06:34 | You started off drawing lines of
varying widths, going from 1 up to 11 and
| | 06:40 | from this X to this Y.
| | 06:43 | Now, let's see how to draw lineCaps.
| | 06:46 | So to draw lineCaps, we are going to go
back to snippets and we are going to copy
| | 06:51 | this code over, and we are going to
copy these lines. Remember, there's three
| | 06:58 | end caps. I will copy that.
| | 07:01 | So we'll paste it below this one here.
| | 07:05 | So notice that we've got three canvases:
| | 07:07 | we have got canvas1, canvas2, and canvas3.
| | 07:09 | So the canvas1 is going to be the line widths.
| | 07:12 | The next canvas would be done with line caps.
| | 07:15 | So let's scroll back up.
| | 07:17 | Here's canvas2.
| | 07:18 | So what we are going to do is draw two
guidelines so we can clearly see how the
| | 07:24 | line ending caps are
different for each operation.
| | 07:27 | So we draw two cyan lines of width 1 at
the left and right side of the canvas, and
| | 07:36 | then we are going to draw
lines using each one of the lineCaps.
| | 07:38 | So we are going to set our lineWidth to be
25 and the strokeStyle is going to be black.
| | 07:43 | And then we are going to draw one line
with the butt style, one with a round
| | 07:46 | style, and one with a square style,
from this position to this position.
| | 07:52 | So we begin the path, we move, we line, we stroke.
| | 07:56 | And then we do it again:
beginPath, moveTo, lineTo stroke.
| | 07:59 | That's the operation for drawing a line.
| | 08:01 | So we save. Let's go back to line
example and refresh, and you can see right
| | 08:07 | there, there is the cyan
guidelines that we drew.
| | 08:09 | There is the first one.
There is the second one.
| | 08:11 | And you can see the start and the
end point for each line goes from one
| | 08:15 | cyan line to the other.
| | 08:17 | So here is the butt example,
| | 08:19 | here is the round example,
and here is the square ending.
| | 08:22 | You can see how each one of those
line caps has a different appearance.
| | 08:28 | And let's finish up using the lineJoins.
So now for the third canvas, we are
| | 08:34 | going to copy these lines right here, go
back to our lines, and we'll paste it in.
| | 08:44 | So, similarly to the last example, we get
the canvas, in this case it is canvas3.
| | 08:49 | We are going to set the lineWidth to 15
and the strokeStyle to black, and then,
| | 08:53 | again, for each one of the lineJoins,
we are going to round, bevel, and miter.
| | 08:58 | So then we begin the path, move, line, and line.
| | 09:01 | So we are going to draw one line up
and one line down, and then we stroke it.
| | 09:06 | So we do one for each of those. We save.
| | 09:09 | Back here in browser, we are going to
refresh, and you can see that the three
| | 09:13 | line joins have now been drawn.
| | 09:14 | So there is the round line join, there
is the bevel line join right there, and
| | 09:19 | there is the miter line join, where the
miter line just continue these two lines
| | 09:24 | here up to a point where they both meet.
| | 09:26 | Now the miter limit controls how much
of a ratio there is before the miter gets
| | 09:32 | cut off and looks like a bevel.
| | 09:33 | So it defaults to 10.
| | 09:34 | Let's go back and play with that for a second.
| | 09:36 | Let's set the context's miterLimit to 20,
and we'll save and let's refresh that.
| | 09:49 | So no effect on that one. Let's try it again.
| | 09:51 | Let's put it down to say 5, refresh.
| | 09:54 | One more time, let's put it down to 1.
And you can see that when I set the
| | 10:03 | miterLimit low enough, suddenly the
miter gets cut off and turned into a bevel.
| | 10:08 | So that's how you use
the miterLimit. All right!
| | 10:11 | So in this example we have seen how to
draw lines of varying thickness, varying
| | 10:16 | end cap styles and varying join styles.
| | Collapse this transcript |
| Understanding the Canvas state| 00:00 | Before we go any further in learning how
to draw on the canvas, we should take a
| | 00:04 | moment and learn about the canvas
state and understand how it works.
| | 00:09 | Each context that you get on a canvas
maintains what's called a drawing state
| | 00:14 | which your code can manage. You can save the
current state and you can restore a previous one.
| | 00:21 | States are basically pushed
onto a stack of saved states.
| | 00:26 | So each time you save a drawing state,
it goes on a stack and then when you
| | 00:29 | restore it, the one that's currently on
the top of the stack gets popped off and
| | 00:33 | becomes the current drawing state.
| | 00:36 | The canvas drawing state keeps track
of several properties of the canvas.
| | 00:41 | It keeps track of the current values
of the lineWidth, the strokeStyle, the
| | 00:46 | fillStyle, the lineCaps, etc.--all the
stuff that we've seen so far in how to
| | 00:50 | draw shapes like rectangles and lines.
| | 00:53 | It also keeps track of what's called
a current transformation matrix, and
| | 00:57 | we'll see that later on in the
course when we use transformations.
| | 01:02 | It also keeps track of the current clipping
region, which also we'll see a little bit later.
| | 01:06 | So it keeps track of each of these
three sets of values and you can save
| | 01:11 | these and restore these.
| | 01:12 | So that begs the question, well,
why would you want to do this?
| | 01:15 | Well, your code may have set of whole
bunch of drawing settings and during the
| | 01:20 | course of drawing, you might want to
just make a minor tweak to one of those
| | 01:24 | settings, but you don't want to have to
keep track of those manually because you
| | 01:29 | will have to remember, oh I changed the
lineWidth here, and I can set it back
| | 01:32 | to it was. Over here I
changed the strokeStyle.
| | 01:35 | Now I've got to set it back to what it was.
| | 01:37 | So, saving and restoring the
canvas does all of that for you.
| | 01:41 | Now to save and restore the state, all you
need to do is use the Save and Restore functions.
| | 01:46 | Essentially, you call context.save
and then you can perform a new set of drawing
| | 01:52 | operations, any one of which might
change any of the save properties:
| | 01:56 | the current lineWidth, the current
fillStyle or strokeStyle, so on and so
| | 01:59 | forth. And when you're done, all you
have to do is called context.restore and
| | 02:04 | that will put the drawing state back
into the state that it was before you
| | 02:07 | called Save and made any changes.
| | 02:10 | So let's actually take a look at how
this works in real code because that's
| | 02:14 | usually the easiest way to understand it.
| | 02:17 | So let's will switch over to my editor, and in
the Snippets code, I am on to the Drawing
| | 02:21 | State section here in chapter 5, so
let's open the example file, and we'll open
| | 02:27 | drawingstate_start.
| | 02:29 | So what we're going to do is go back
to my snippets and we're going to copy
| | 02:34 | these lines over here. For now
we'll just copy those and we'll paste.
| | 02:43 | So let's see what we've
got so far in the browser.
| | 02:45 | Let's go over here and go to
drawingstart, so we've got a rectangle that has a
| | 02:50 | yellow interior and a red stroke.
| | 02:52 | Now, let's go back to the snippets
and copy the next group of lines over.
| | 02:58 | I'll copy these and we'll paste below this.
| | 03:05 | So for the moment, I'm going to comment
out the calls to save and restore, and
| | 03:13 | let's take a look at the effect.
| | 03:14 | So here we draw the first rectangle.
It's got a red stroke in the yellow
| | 03:18 | interior. Then we'll go and we change
the strokeStyle to be green and the
| | 03:23 | fillStyle to be blue and the lineWidth
to be five. And then we create a new
| | 03:26 | rectangle, and then we create a
third rectangle, but we don't have any
| | 03:30 | properties that were being set, so
let's go ahead and save, and let's go back
| | 03:35 | to the browser and refresh.
| | 03:36 | So now we have three rectangles: one is
yellow inside in red, and then we have
| | 03:41 | two rectangles that are blue
interiors and green strokes.
| | 03:45 | So let's go back to the code now.
Let's uncomment those two lines.
| | 03:50 | I'm going to uncomment Restore.
| | 03:51 | I'm going to uncomment Save.
| | 03:55 | So the call to the save function
will save the current properties of the
| | 04:02 | context--in this case the stroke, fill
and line. Then we reset them over here
| | 04:07 | and draw a new rectangle, and then we
restore them. So let's now save and let's
| | 04:11 | go back to the browser.
| | 04:12 | So now when we refresh, you can see
that the call to the restore function is
| | 04:18 | restoring the drawing properties that
were set originally for this rectangle
| | 04:23 | before they were changed for this one.
| | 04:26 | So again back in the code. So we start
off with red and yellow. Then we save that.
| | 04:33 | We do a whole bunch of things here
that changes the current drawing context,
| | 04:37 | and then we call restore. And that
pops off the stack that original context
| | 04:42 | that we saved which restores the red and
yellow settings, allowing us to draw with them again.
| | 04:47 | So we can see how using the Save and
Restore functions to manage the canvas
| | 04:52 | state can save us a lot of work when
we're drawing things and making minor
| | 04:57 | changes all over the place.
| | 04:58 | Now, this may seem like a trivial example,
but later on when you're drawing really
| | 05:02 | complex drawings and you're making
minor changes to the drawing context property,
| | 05:06 | this really comes in handy and
relieves your code from having to do a lot of
| | 05:10 | manual work to keep track of drawing
properties, of which there are a lot.
| | Collapse this transcript |
| Drawing complex shapes: Arcs and paths| 00:00 | Up until now, we've seen how to draw
simple shapes like rectangles and lines.
| | 00:05 | Now let's take a look at drawing more
complex shapes, specifically arcs and paths.
| | 00:10 | So, what is a path? A path is basically a set
of connected points, and the points are connected by
| | 00:16 | lines or by curves, and a
path is either open or closed.
| | 00:21 | The current drawing context always has
one, and only one, current drawing path.
| | 00:26 | Now, paths can be open or closed.
| | 00:28 | A closed path has an end point that is
the same as its starting point. Or the
| | 00:34 | canvas can automatically draw a line
from the ending point to the starting point
| | 00:39 | and automatically close the path for you.
| | 00:42 | Now, to begin creating a path, you use
the beginPath method, and it doesn't
| | 00:46 | take any arguments.
| | 00:47 | You just simply say beginPath
and start drawing your paths.
| | 00:51 | To add paths, you basically use one or
more path-drawing routines, and if you've
| | 00:55 | watched me in the previous movies,
you've seen how to do this with lines.
| | 00:59 | In this movie, we're going to
see how to do it with arcs.
| | 01:01 | To stroke the current path, you just
call the stroke function, again with no
| | 01:04 | arguments. And to fill it, you just
call fill. Both of those are no argument
| | 01:09 | functions that will stroke and fill paths.
| | 01:11 | And to close the current path, should you
decide to close it, you just call closePath.
| | 01:16 | In case the end point is not the same as the
start point, the canvas will close it for you.
| | 01:20 | Let's talk about arcs for a moment.
Arcs are curves that are portions of a
| | 01:25 | circle, and in fact a circle is an arc.
| | 01:28 | It's just a special case.
| | 01:29 | It's a full 360-degree arc.
| | 01:32 | So to draw an arc, you can either use
the arc function or the arcTo function.
| | 01:37 | So the arc function has several
arguments. The first is the X and Y point, that
| | 01:43 | if the arc was a full circle, would
serve as the center of the circle.
| | 01:48 | The r argument is the radius, which is
how far the arc is out from this imaginary
| | 01:55 | circle center right here.
| | 01:56 | Now, to actually stroke the path
along the edge of the circle that the arc
| | 02:00 | represents, you have a
starting angle and an ending angle.
| | 02:04 | And then the last argument is true if
you want the arc to go anticlockwise
| | 02:09 | rather than clockwise,
which is the default direction.
| | 02:12 | Now, the other arc function is arcTo,
and that takes two control points and a
| | 02:18 | radius. And then finally the
closePath function, which I mentioned earlier,
| | 02:22 | which closes the current drawing path.
| | 02:25 | Now we should make a special note that
when you use angles, such as the angles
| | 02:29 | here, these angles are
radians; these are not degrees.
| | 02:34 | So if you want to use degrees for your
arguments instead of radians, you can use
| | 02:38 | a very simple mathematical
function right here, which takes Math.PI,
| | 02:42 | you divide by 180, and you multiply by
degrees and that will give you radians.
| | 02:47 | Let's take a look at some arc examples.
Remember 360 degrees is the same as 2 pi radians.
| | 02:54 | So in this arc, we have a starting point
and an ending point, and the way we
| | 02:58 | do that was by stroking a 90-degree arc.
| | 03:01 | So we call beginPath to begin the
path, and we create an arc with its center
| | 03:06 | point at 50 and 150. That will be
right about this center point right here.
| | 03:11 | This 100 value is the radius, which is
about 100 pixels from the center out to
| | 03:16 | the edge of the arc.
| | 03:18 | Then we start at the 1.5-radian mark,
and we go to the 2-radian mark, so we'll
| | 03:24 | start there and it will
end at this angle right here.
| | 03:27 | Let's look at another example.
| | 03:29 | In this case, we have an arc that's going
the other way. So to stroke 270 degrees
| | 03:34 | arc, again, we call beginPath.
| | 03:36 | We have the X and Y center--that will be
this center point right here. Radius is
| | 03:41 | still 100. And we're going from the
zero-angle part all the way around here to
| | 03:47 | the 1.5-radian mark, anticlockwise in this case.
| | 03:51 | So let's actually take a look at some real
examples in code to see how this works.
| | 03:55 | Here we are on the code editor, and I've
got my snippets open to the paths section,
| | 04:00 | and I've got my paths_starts
example file for this chapter opened up.
| | 04:06 | So let's go ahead and copy and paste
some of these examples. So I will take
| | 04:11 | these first lines right here, along with
the first example, I'll copy and paste,
| | 04:16 | okay, and save. And let's go to the
browser, and we'll choose paths.start.
| | 04:24 | You can see that we've got three line
segments for this particular path.
| | 04:27 | Let's take a look. We've got the strokeStyle
blue, a fillStyle of red, which we are
| | 04:32 | now currently using.
| | 04:33 | The lineWidth is 5, and here's where we are
to draw the open path. So we call beginPath.
| | 04:39 | We move the pen to its starting location,
| | 04:41 | we add three line segments, and then we
stroke, and that will stroke the current
| | 04:45 | path so those three lines segments gets drawn.
| | 04:47 | Okay, let's copy the next one.
| | 04:53 | This time we're going to draw a
closed path, so we'll copy and we'll paste.
| | 05:00 | So in this case, we call beginPath like
we always do. Same kind of operation.
| | 05:03 | We move the pen, draw three line segments, only
| | 05:06 | in this case we call closePath before
we call stroke. So let's save and let's
| | 05:12 | go back to the browser and refresh. And you can see
that there's the same three line segments,
| | 05:16 | but in this case because of the
closePath call, the canvas added this final line
| | 05:21 | for us to make the ending point
the same as the starting point.
| | 05:25 | One more example. Let's go back
to the code, back to the snippets.
| | 05:30 | This time we're going to draw a closed path.
| | 05:33 | So I'm going to copy these lines
here. Now we're going to paste.
| | 05:38 | So one more time, three line segments,
only in this case, in addition to stroke,
| | 05:43 | we're going to call fill--and
notice there's no closePath call here.
| | 05:48 | So we save, and then we go back to the
browser and we refresh. And in this case
| | 05:53 | you can see that the path was stroked--
| | 05:55 | it's not closed, but it was
filled in as if it were closed,
| | 05:59 | there is an imaginary boundary
right here--using the current fillStyle.
| | 06:03 | So now that we've seen paths,
let's take a look at arcs.
| | 06:07 | I have got my arcs_start example
open right here, go back to my snippets.
| | 06:15 | Let's go back up to the
arcs, which are right here.
| | 06:21 | I am going to copy the
first example here and paste it.
| | 06:30 | We'll save, and let's show it in the browser.
| | 06:34 | So that's the 90-degree arc right
there. And just to show you the effect of
| | 06:39 | changing the radius, let's
make the radius 150 this time.
| | 06:45 | Save, and we'll refresh and watch.
So you can see that the center point stayed
| | 06:51 | the same, but the radius got bigger.
| | 06:54 | Let's copy some more. In this case,
I want to copy this one, and then we'll paste.
| | 07:05 | Now in this case, we're going to stroke
a three-quarter arc. So we've moved the
| | 07:10 | center point over and we have got
100 radius. And in this case we've got
| | 07:14 | these two angles, right?
| | 07:16 | We've got a starting angle. We've got an ending angle.
So we're going to save that and refresh it.
| | 07:20 | You can see that the arc has now been
drawn in the counterclockwise direction,
| | 07:26 | starting from here, going all the way
around three quarters to this point,
| | 07:30 | around that center point right there.
| | 07:31 | Okay, last example. Let's do a
circle, and we'll copy and we'll paste.
| | 07:43 | All right, so in this example,
we've started at zero. We go the full 2 pi
| | 07:48 | radians. Save, we refresh,
and there's our circle using the fill and stroke
| | 07:56 | style, because you can see
we call both fill and stroke.
| | 08:00 | And just to show you how radians work,
let's just do a simple example with degrees.
| | 08:05 | Let's just say 'var degrees equals
360', and we'll say 'var radians equals
| | 08:14 | Math.PI/180 * degrees',
and we'll just substitute radians in
| | 08:25 | there for this one.
| | 08:28 | Now since we're starting off with 360,
it's going to have no effect. But just to
| | 08:31 | show you that it is the same,
let's refresh. So it's the same.
| | 08:35 | But let's just change that to I don't
know, 173 degrees, and we'll save, and
| | 08:42 | we'll refresh. And you can see that
it's not quite half a circle, because it's
| | 08:46 | not 180 degrees, but you get the idea.
| | 08:49 | You can use radians, or you can
have degrees and convert them to radians.
| | 08:53 | What we've seen in this example is how
to draw paths and arcs using the canvas
| | 08:59 | path- and arc-drawing routines.
And we've seen how to draw open and closed paths,
| | 09:05 | as well have stroke and fill paths.
And then finally, we saw how to draw arcs in
| | 09:10 | both directions using radians and degrees.
| | Collapse this transcript |
| Drawing complex shapes: BƩzier and quadratic curves| 00:00 | You can actually get fairly advanced
with some of the drawing operations that
| | 00:04 | are possible with the canvas.
| | 00:06 | In fact, the canvas lets you
draw Bezier and quadratic curves.
| | 00:11 | The way curves are drawn is in the case
of Bezier curves, there is a starting
| | 00:17 | context point, and an end point that
uses two what are called control points to
| | 00:23 | determine how the curve is drawn.
| | 00:26 | Quadratic curves are similar.
| | 00:28 | They use a start point, but they only
have one control point and one endpoint.
| | 00:33 | So Bezier curves because of those two
control points, they let you draw curves
| | 00:37 | that are slightly more complex.
| | 00:39 | So let's take a look at each one.
| | 00:41 | The Bezier curve has a starting point,
which is right here, the context point.
| | 00:46 | That's the end point right there.
And there are these two control points.
| | 00:50 | These two control points control how
the line curves towards the control
| | 00:56 | point in each case.
| | 00:57 | So you can see that because this
end point is close to its control point, the
| | 01:01 | curve is a little bit different
over here than it is over here.
| | 01:03 | And for quadratic curves
there's only one control point.
| | 01:07 | So you set the context point, set the
control point, and the end point and you
| | 01:11 | can see that the curve is slightly less
complex than what you get with Bezier curves.
| | 01:17 | So the functions for drawing
these curves are right here.
| | 01:21 | So like other paths, you first use the
moveTo function, which we saw when we
| | 01:27 | learned how to draw lines in a previous movie.
| | 01:29 | So you move to a pen location,
and then you call bezierCurveTo, and then you
| | 01:35 | supply a series of points. cx and
cy represent the control points.
| | 01:41 | So this is the first control point,
| | 01:42 | this is the second control point,
and then this is the end point.
| | 01:46 | It's similar for quadraticCurveTo: you
use moveTo to move to a start point, and
| | 01:52 | then you supply a control
point and an ending point.
| | 01:55 | So let's take a look at
this in a real live example.
| | 02:01 | So here I am in the code editor, and I've got
my curves section right here of my snippets.
| | 02:07 | So let's open up an example file, and
what we're going to open up is curves_start.
| | 02:14 | This is the starting
point for our curves example.
| | 02:18 | So I'm going to go and
copy the first example here.
| | 02:22 | So we'll pick up the stroke and
lineWidth properties, and we will call this
| | 02:28 | right here, and we'll paste this in and save.
| | 02:33 | All right, let's take a look at
how this looks in the browser.
| | 02:36 | We should have a Bezier curve that's 5
pixels wide and blue; sure enough, we do.
| | 02:42 | Now that's pretty cool, but we can
make it a little bit more instructive to
| | 02:45 | actually see where the control points are.
| | 02:47 | So let's go back to the code, and we'll
go back to the snippets. And what we're
| | 02:52 | going to do now is make
the control points visible.
| | 02:55 | So we'll copy and we'll paste this code in.
| | 03:00 | So what we have here now is a full example.
| | 03:03 | So we call beginPath, like we do with all paths.
| | 03:06 | We move it to a location. Then we call
the bezierCurveTo, and we supply a whole
| | 03:10 | bunch of points that determine how the
Bezier curve is drawn. And then we call
| | 03:14 | stroke to actually fill it in. And to
make the control points visible, we're
| | 03:18 | going to define a strokeStyle that's 25%
opacity of black with a pixel width of 1.
| | 03:26 | And then we're going to simply call
moveTo and lineTo. And if you look, we're
| | 03:31 | basically going to line-to each one of
the control point locations, so that
| | 03:36 | we can see what effect the control points have
on each one of the points on the Bezier curve.
| | 03:42 | So let's save and let's refresh, and you
can see that these are where the control
| | 03:46 | points are up here now, and we can
actually change the control points.
| | 03:52 | So what we can do is change that one to say
300, and that's this guy here. So let's save.
| | 04:03 | Let's refresh.
| | 04:05 | You can see the effect of moving
the control point to no location.
| | 04:09 | So there is the curve.
| | 04:10 | You can see that the curve is
being affected by these control points.
| | 04:15 | So now, let's do a quadratic curve. Same idea.
| | 04:24 | We're going to take the curve and the
control points, copy, and we're going to
| | 04:30 | come out of here and paste those in.
| | 04:34 | So now in this case, we have a green
line that's five pixels wide and just like
| | 04:41 | with all paths, we begin the path.
| | 04:43 | We move to the starting location,
and then we call quadraticCurveTo, and we
| | 04:48 | supply the necessary points there.
| | 04:49 | There is the control point, there's the
ending point, and we call stroke to make
| | 04:54 | the curve visible. And then we have
some instruction code right here that makes
| | 05:00 | the control point visible. So let's save.
| | 05:04 | Let's refresh.
| | 05:05 | You can see that now here's our
quadratic curve, and there's the control point up
| | 05:09 | there, and we can play with that a little bit.
| | 05:12 | So it starts out at 400, 200--that's the
starting point--and then the curve goes
| | 05:18 | straight up from there.
| | 05:19 | So let's actually move that one over a
little bit, to 500 say, and we'll change
| | 05:26 | the instruction code as well, and we'll
refresh. You can see that by moving
| | 05:32 | the control point, that affects the curve.
| | 05:34 | In this example, we've seen how to draw
curves using Bezier and quadratic math,
| | 05:39 | and we've seen how changing the control
points changes how the curves are drawn.
| | Collapse this transcript |
| Rendering text| 00:00 | One of the interesting things about
canvas is that in addition to drawing shapes
| | 00:04 | and curves and paths and so on, you can
also draw text directly onto the canvas
| | 00:10 | using a variety of text-drawing settings.
| | 00:13 | In fact, drawing text is very
similar to drawing any other paths.
| | 00:19 | You can stroke them.
| | 00:20 | You can fill them using the same
fillStyle and strokeStyle as you would for
| | 00:25 | other path operations
and other shape operations.
| | 00:29 | It's important to note that when you
draw text on the canvas, it is not
| | 00:33 | affected by any kind of CSS box model;
| | 00:37 | it's just a path, and it's drawn using
the canvas rules, not any CSS rules that
| | 00:43 | you may have defined elsewhere in your document.
| | 00:48 | And it's also important to note that
you shouldn't use text on the canvas as a
| | 00:53 | replacement for regular document
text, because that makes accessibility
| | 00:57 | really, really hard.
| | 00:58 | In fact, screen readers won't be able to
read the text that you draw on the canvas.
| | 01:03 | So if you have any grand ideas about
using canvas to replace headings, like h1s
| | 01:07 | or h2s and so on, it sounds like a
great idea, but you probably should find
| | 01:12 | another way to do that, because
accessibility-wise, that's just not going to
| | 01:16 | work for people who rely
on assistive technologies.
| | 01:21 | So to draw a text on the canvas, we
use some text-drawing properties and
| | 01:26 | methods, and those are here.
| | 01:28 | So we can set a couple of properties.
| | 01:29 | First, you can set the font that you
want to draw with, and anything that you
| | 01:34 | would normally put into a
font CSS rule can go in here.
| | 01:37 | And then you can also set
textAlign and textBaseline.
| | 01:41 | textAlign can be either a start,
which is the default, which is where the
| | 01:45 | drawing point starts.
| | 01:46 | There's end, and there's
left, right, and center.
| | 01:50 | For textBaseline, there's a couple of
different settings. Some of these are
| | 01:54 | pretty advanced, so I'm not going to
go very deep into them. There's top.
| | 01:57 | There's middle or bottom, which you
may be used to from regular HTML. But there's
| | 02:01 | also things like ideographic and
hanging, and those are mostly used for
| | 02:06 | languages such as, for example, Chinese
or Korean, where there's an ideographic
| | 02:11 | baseline involved with
particular characters and so on.
| | 02:14 | The point is that the canvas does give you
that kind of control over how text is drawn.
| | 02:19 | Those three properties are
available for setting how text is drawn.
| | 02:23 | It's very similar to how you set fillStyle or
strokeStyle for strokes and fills and so on.
| | 02:28 | Then the next few
routines actually draw the text.
| | 02:32 | So there's the fillText method, which renders
the text string supplied by the txt argument--
| | 02:39 | that's the string that you want to draw--
at the point of x and y. And then this
| | 02:45 | parameter here (maxW), that's optional,
which is why it's in these brackets.
| | 02:50 | If you specify a maxWidth, then the
canvas will render that string no wider
| | 02:55 | than this space right here.
| | 02:57 | So it will compress the characters if
it needs to, or do what it can do to make
| | 03:02 | the string fit into that space.
| | 03:04 | And along with fillText,
there's strokeText. Same idea here.
| | 03:08 | You give it the text to stroke,
| | 03:10 | you give it the point that you
want the text to be drawn at, and an
| | 03:15 | optional maximum width.
| | 03:17 | And the last function, measureText,
will return the dimension metrics of the
| | 03:23 | string that you pass in using whatever
the current font settings up here that
| | 03:28 | you happen to pass in.
| | 03:30 | So let's take a look at some
text drawing examples in real code.
| | 03:36 | Okay, so here we are in the
editor, and in my Text section of my
| | 03:41 | ExampleSnippets, I'm going to open up
the text_start example. And we're going to
| | 03:50 | go back to the Snippets,
and we'll copy some code over.
| | 03:53 | So the first one is the string that
we're actually going to draw, and we'll copy
| | 03:56 | the first example and we'll
paste that in, so we'll save.
| | 04:03 | So this is a really simple example.
| | 04:04 | I've got a string I want to render,
and I'm just going to render it using
| | 04:09 | whatever the default settings are
for rendering text onto the canvas.
| | 04:15 | So let's save that, and let's go
ahead and look at that in the browser.
| | 04:18 | And you can see that it defaults to
a pretty small text size, and it draws
| | 04:23 | the text right at the point where I said to
draw it about 10, 20, which is right up there.
| | 04:28 | So let's go back to the code and do
some more advanced stuff, and let's go
| | 04:33 | back to the snippets.
| | 04:35 | This time, let's draw the
string with some font information.
| | 04:41 | So we'll place that.
| | 04:45 | So now on the drawing context, I've
set the font to be 25pt Georgia, and now
| | 04:54 | we're going to fill the text at a
different point below the first one, and we'll
| | 04:59 | see what effect that had. So we'll Refresh.
| | 05:02 | So you can see that now the text is
being drawn in a much bigger font and a
| | 05:07 | different font face.
| | 05:09 | Let's keep on going.
| | 05:12 | Go back to my Snippets, and this time
we're going to fill it, but we're going
| | 05:15 | to use a fillStyle color. So I'll copy
these lines and paste them in there and save.
| | 05:24 | So now we're using a blue fillStyle to
fill the text, and let's see how that works.
| | 05:28 | Okay, that was pretty cool.
| | 05:30 | So this time same string,
only different color now.
| | 05:33 | Let's go back to the code.
| | 05:34 | Okay, now let's draw the string
with both a stroke and a fill.
| | 05:43 | We'll copy and we'll paste.
| | 05:50 | So in this case, I have
defined a font of 32pt Verdana.
| | 05:54 | We've got a fillStyle, we've got a
strokeStyle, and in this case, the
| | 05:58 | strokeStyle is green at 80% opacity,
and we're going to fill and stroke the text this time.
| | 06:06 | So let's do that.
| | 06:07 | Okay, a little bit different effect there.
| | 06:10 | Let's uncomment this line that
sets the baseline, just to show you how
| | 06:14 | setting the baseline works.
| | 06:15 | So we'll save, and so here's the effect.
| | 06:18 | When I Refresh, you can see that the
text shifted down a little bit. So let's go
| | 06:24 | ahead and put that back out again and
refresh, get it back to what it was.
| | 06:30 | And then finally, for the last example,
let's use the measureText and let's put
| | 06:37 | an exclamation point in here, just to
show you how this works. And we'll go down
| | 06:42 | here, and we'll copy the
measureText, and I'll explain this.
| | 06:49 | Now, let's go down, and I'll paste it in.
| | 06:55 | So in this case, we're going to call the
measureText function, and when you call
| | 07:02 | measureText on theString, which in
this case has been set to the text string
| | 07:06 | that we're using, it's going to take
the current font settings and then measure
| | 07:10 | how wide the text is.
| | 07:13 | There's no built-in method to measure
how tall the text is, but you can fake
| | 07:19 | that up pretty easily by creating a
fake span and putting the text inside the
| | 07:24 | span and then using the CSS features
available in your browser to see how high
| | 07:27 | the span is, and that will tell you
how high the text is. But there's no
| | 07:31 | currently built-in way of doing that.
| | 07:33 | So this is a simple example.
So we're just going to calculate the width.
| | 07:37 | Now I'll come back here, and actually this
comes back with an object that has a width property.
| | 07:43 | So then we'll call beginPath, we'll set
the strokeStyle to black, and then we're
| | 07:47 | going to move to a point that's
underneath the text string, and then we're going
| | 07:52 | to create a line that is the
width of the text at the same Y point.
| | 07:58 | So I'm going to underline the text,
and then we call stroke to fill that line in.
| | 08:03 | So let's save, and let's refresh.
| | 08:07 | And you can see that in this case,
now that I've modified the string with
| | 08:10 | exclamation points, the text has changed.
And we now have a black line going from
| | 08:16 | the part where we started drawing the
text down to where the character is.
| | 08:20 | You can see that there's a little
bit of space left over here, and the
| | 08:23 | reason for that is because actually
when you call the measureText function,
| | 08:27 | the measureText result that comes
back is not always exactly the same size
| | 08:31 | as the text string.
| | 08:32 | In fact, the specification that the W3C
makes states that there is currently no
| | 08:37 | way of finding out what the exact
bounding box of the text currently is.
| | 08:44 | That might be added to a future
version of the spec, but it's not there now.
| | 08:49 | So the lesson to take away from this is
there's currently not a way to measure
| | 08:53 | exactly how wide a string is, in
order to build something, say like a text
| | 08:59 | editor using the canvas.
| | 09:01 | They're looking at putting that
in, but it's not there right now.
| | 09:04 | Anyway, in this example we've seen
how to draw text on the canvas using a
| | 09:08 | variety of settings, strokes, colors, and fills.
| | 09:11 | We've seen how to measure the width of
the text, and we've seen how to draw
| | 09:15 | text using both strokes and fills.
| | Collapse this transcript |
|
|
6. Complex Canvas Drawing TechniquesCreating shadows| 00:00 | In this chapter we're going to
take a look at using some more complex
| | 00:03 | canvas drawing techniques, and the first one
we're going to look at is creating shadows.
| | 00:09 | So there are four attributes that you
can use to draw shadows on the drawing
| | 00:15 | context on the canvas.
| | 00:17 | And all drawing operations that take
place on the canvas are affected by
| | 00:23 | these shadow attributes.
| | 00:25 | This includes paths, images,
text, lines, whatever.
| | 00:28 | When you draw shadows, they can be
colored, they can be offset in both the X and
| | 00:37 | Y direction, and they can have a blur value.
| | 00:40 | And in fact, these right here are the
available properties to use when drawing a shadow.
| | 00:46 | So the first one is the shadowColor, and
that's the color to use when drawing the shadow.
| | 00:51 | And again, like other places where you
can set a color, you can use any kind of
| | 00:55 | CSS color string to specify a color.
| | 00:58 | Now if you don't specify one,
it defaults to transparent black.
| | 01:02 | The OffsetX and OffsetY
properties are pretty self-explanatory.
| | 01:08 | They control the horizontal offset of
the shadow, which defaults to 0, and the
| | 01:12 | vertical offset, which also defaults to 0.
| | 01:16 | And there is a Blur factor that
you can set on the shadow as well.
| | 01:20 | This defaults to 0, but it has to have a
value that's greater than 0 in order to
| | 01:25 | have any visible effect.
| | 01:28 | So let's jump over to the code
and take a look at drawing shadows.
| | 01:34 | Here we are in the code, and I've got
my shadows_start file opened up, and that
| | 01:41 | is located in the folder for chapter 06.
| | 01:44 | So let's just take a quick look at that in
the browser, take a look at shadows_start.
| | 01:49 | So we start off with an empty canvas,
which is only visible by its dotted
| | 01:53 | outline, and we'll go back over to the code.
| | 01:56 | In my Snippets file, under the section for
Shadows, I am going to copy some code over.
| | 02:03 | So this first set of lines here
basically sets up some basic shadow settings, so
| | 02:08 | I'll copy those and I'll bring those
over here in the section where we've tested
| | 02:14 | for the canvas and gotten the context.
| | 02:16 | We're going to set some shadow settings,
so here you can see I'm setting the
| | 02:20 | shadowColor to black and the Offsets
to 10 pixels in both X and Y, and I'm
| | 02:26 | giving it bit of a Blur factor.
| | 02:28 | And then I'm going to copy the first example.
| | 02:32 | So let's copy that and bring it over.
| | 02:36 | So, in this case, we've created a
rectangle using the fillRect function right
| | 02:42 | here, along with a fillStyle.
| | 02:44 | And the fillStyle is basically going to
fill this rectangle with a blue color,
| | 02:49 | at 100% opacity, and make a
rectangle 200 pixels wide and 100 high.
| | 02:55 | And because we've set up some shadow
properties here, it will draw a shadow
| | 03:00 | behind the rectangle.
| | 03:02 | So let's go back to the
browser, and we'll refresh.
| | 03:06 | And you can see that there's the blue
rectangle, and there's the shadow behind it.
| | 03:09 | And let's take a look at
this in some other browsers.
| | 03:14 | So we'll just right-click
and we will say Open with.
| | 03:17 | In this case, let's take a look at Firefox.
| | 03:18 | Okay, there's the same effect in Firefox.
| | 03:21 | There's the shadow.
| | 03:23 | Let's take a look in Opera. And you can
see there's the shadow around the object
| | 03:28 | in the Opera browser.
| | 03:30 | Let's just do one more.
| | 03:31 | Let's go ahead and look at this in Chrome.
| | 03:35 | And there it is in Chrome.
| | 03:36 | There's the shadow
around the object right there.
| | 03:39 | Let's go back to the code.
| | 03:41 | Let's get another example.
| | 03:43 | In this case, let's use some text.
| | 03:45 | Let's see what drawing a
shadow on a text looks like.
| | 03:51 | So we'll come back and we'll paste this in.
| | 03:54 | So in this case, we have a text string,
and we are setting the fillStyle to be
| | 04:01 | green. And here I'm changing the shadow colors.
| | 04:05 | So in this case, the shadow is a bit
of a combination of the green and blue
| | 04:11 | colors at half opacity.
| | 04:13 | I've changed the Offset, so I have
changed the Blur, and I've also set the font
| | 04:16 | size to be a little bit larger.
| | 04:18 | So when we go to fill the text, we should
see a different color shadow behind the text.
| | 04:26 | So let's save.
| | 04:28 | Let's look at it in IE.
| | 04:30 | And sure enough, you can see there's the text.
| | 04:31 | There's the shadow behind it.
| | 04:33 | And let's go back to Firefox.
Do the same thing. Yup!
| | 04:37 | That works. And let's look at it in Chrome.
| | 04:40 | Sure enough, it all seems to work just fine.
| | 04:44 | Let's go back to the code and
let's look at another example.
| | 04:50 | In this case, we're going to do it on a
line. So we'll copy, and we will paste.
| | 04:59 | So in this case, now we have a line,
and I've got a round line cap with a width of 25.
| | 05:05 | And once again, changing
some of the shadow properties,
| | 05:09 | in this case, making more of a purple
color with a higher Blur number. And the
| | 05:14 | strokeStyle is going to be red.
| | 05:16 | We're going to have a red line with a
round line cap that's 25 pixels wide.
| | 05:20 | So we begin our path, we do the moveTo
and lineTo, and when we call the stroke
| | 05:25 | function. That is when the
shadow gets created. So let's save.
| | 05:31 | Let's refresh IE.
| | 05:32 | You can see there it is, and there's
that little purply kind of shadow behind it.
| | 05:36 | And let's do the same thing in Firefox.
| | 05:39 | Yeah, it works fine.
| | 05:41 | Let's go to Chrome.
Yeah, works fine there too.
| | 05:44 | Before we go, let's just take a look
at some things we can do with shadows.
| | 05:48 | What I'm going to do is I'm actually
going to take the shadowOffset here and
| | 05:54 | down here, I'm actually going
to make these negative numbers.
| | 05:58 | So I'm going to do -15 and -15, and we'll save.
| | 06:04 | Okay, now let's go back
to the browser and refresh.
| | 06:07 | So you see how the shadow in that case
moved up and to the left behind the object.
| | 06:13 | So in addition to specifying positive
numbers which moves the shadow to the
| | 06:17 | right on the X axis and down on the Y
axis, by specifying negative numbers, we
| | 06:24 | can move the shadow up and to the left.
| | 06:27 | So negative X means go to the
left, and negative Y means go up.
| | 06:32 | So in this example, we've seen how to
draw shadows with varying colors, varying
| | 06:35 | blur effects, and varying
offsets using the shadow properties.
| | Collapse this transcript |
| Drawing with patterns| 00:00 | The HTML5 canvas element makes
it easy to draw using patterns.
| | 00:04 | In fact, drawing operations that use
fill and stroke styles can take patterns, as
| | 00:09 | well as gradients, as settings.
| | 00:11 | The way you create a pattern is from an
image, a video, or another canvas element.
| | 00:17 | So if you use an image that's an
animated image, the pattern that you create
| | 00:21 | will use the poster frame of
the animated image as the pattern.
| | 00:25 | And if there is no poster frame in the
animated image, it will use the first
| | 00:28 | frame of the animation.
| | 00:31 | For video, the current
playback frame is used as the pattern.
| | 00:36 | It's not the live video;
| | 00:37 | it will actually grab a frame
and it will use it as the pattern.
| | 00:40 | So at whatever point you create the
pattern, then it will choose whatever frame
| | 00:44 | happens to be drawn at that point and use it.
| | 00:47 | Patterns can be set to repeat.
| | 00:48 | They can either repeat not at all, or in
both dimensions, or only in X or Y dimensions.
| | 00:55 | So to create a pattern, it's pretty simple;
| | 00:57 | you basically use the createPattern function.
| | 01:01 | So createPattern takes two arguments.
| | 01:03 | The first one is an element and that has to
be either an image, video, or canvas element.
| | 01:08 | The second argument can be
one of these four strings:
| | 01:11 | no-repeat, repeat, repeat-x, or repeat-
y--pretty much just like any other CSS
| | 01:16 | background property you would set on an image.
| | 01:18 | All right, let's jump over to the code and
actually take a look at patterns in real life.
| | 01:24 | Okay, so here I am in the code. I'm at my
Patterns section in my Snippets file, and
| | 01:29 | I've got my patterns_start
file open from chapter 06.
| | 01:33 | So let's start making some patterns.
| | 01:35 | The first thing I want to do is
create a pattern from an image.
| | 01:39 | So I'm going to copy this example
right here and paste it in, and I'll save.
| | 01:47 | So to create a pattern from an image,
I'm actually going to create a new image
| | 01:51 | object using the DOM and then load the image in.
| | 01:54 | Now, because images might load
slowly over the network, if I try to just
| | 01:58 | simply create a pattern right away,
that might give me an error because the
| | 02:02 | image hasn't loaded yet.
| | 02:03 | So to prevent that, I'm going
to use an onload function here.
| | 02:06 | So when the onload function completes,
that's when my createPattern method will
| | 02:11 | be called, and then we'll fill the rect
of the canvas with a rectangle that uses
| | 02:16 | its fillStyle as this image pattern.
| | 02:19 | So the image we're going to use is
this one right here. And if we look at the
| | 02:24 | examples, it's this little image right here.
| | 02:27 | We're going to tile the
background on the canvas with this image.
| | 02:30 | So let's go ahead and do that.
| | 02:32 | So what we do is we create the image.
Then we set the onload function. Then we
| | 02:37 | set the source of this image to be the
path to that image. That will cause the
| | 02:41 | image to load. And then when the load
completes, this function will be called.
| | 02:45 | Then we tell the context to go ahead
and use the fillStyle, set the results of
| | 02:51 | the createPattern function into the
fillStyle, and then we fill the rectangle,
| | 02:55 | starting at the upper left of the
canvas and all the way across the canvas to
| | 02:59 | the width and height.
| | 03:00 | So let's save this and try it out.
And you can see that we've got a nice little
| | 03:05 | repeating tiled image here, and now if
you just say repeat-x, save, refresh,
| | 03:13 | right, we only get the X direction.
| | 03:16 | Let's go back and change that, and
let's try it in one other browser.
| | 03:20 | We'll try it in Firefox. And you
can see the results are the same.
| | 03:24 | So, now let's make another pattern and
let's get rid of this one to avoid competition.
| | 03:30 | So in this case, now we're going
to create a pattern from a video.
| | 03:34 | So I'll copy this over, and
I'll show you what we're doing.
| | 03:38 | So down here in the document, I've got a video.
| | 03:41 | This is an HTML5 video element with an
ID, and it's pointing at this source right
| | 03:46 | here, and it's hidden from view.
| | 03:49 | So let's take a look at the
source. It's this video right here.
| | 03:53 | So I'll bring this up in the player.
| | 03:55 | Let's take a quick look at it.
| | 03:56 | Okay, so this is the video that
we're going to use as our pattern.
| | 04:01 | Now to use the video as the pattern,
remember that when we create the pattern,
| | 04:06 | it's going to grab the current playback frame.
| | 04:09 | So what we need to do is set a
timeout function in order to grab a pattern
| | 04:14 | that's a few seconds into the video.
| | 04:17 | So I'm setting a timeout that's waiting
3000 milliseconds, or 3 seconds, and when
| | 04:22 | the timeout function completes, my
resulting function is going to go get the
| | 04:26 | video element from the document,
get the canvas, and get the context,
| | 04:30 | and then create a pattern from the
video element and set that as the current
| | 04:36 | fillStyle of the context.
| | 04:38 | And then when I call the fillRect
function, again, covering the entire canvas,
| | 04:43 | the rectangle will be filled with
repeating images of whatever frame was playing
| | 04:48 | at 3 seconds into the video.
| | 04:51 | So let's save, and let's put a
little autoplay on the video right there.
| | 04:58 | That way it plays automatically.
And we'll bring it up in the browser.
| | 05:02 | Okay, the video is playing. 1, 2, 3. All right!
| | 05:07 | So, at 3 seconds, you can see that what
happened was the frame got grabbed at the 3-
| | 05:11 | second index and was filled into the
entire canvas right here. And because of the
| | 05:17 | repeat, the image is repeating across.
| | 05:20 | So it's creating a pattern from video.
| | 05:22 | Let's go back and let's get rid of
this one, and we'll take that off as well.
| | 05:32 | The last example, I'm going to create
a pattern from another canvas, and that's
| | 05:39 | this one right here.
| | 05:41 | So we'll copy that, and we will paste.
| | 05:45 | So let me explain what's going on here.
| | 05:48 | Once again, we look down at the
document, and I've actually got two canvasses.
| | 05:52 | Here is the example canvas that we've
been using throughout the course that
| | 05:55 | we've been drawing our results into.
| | 05:57 | I also have another canvas down here
with a width and height of 25. And I'm
| | 06:02 | going to draw some content into that
canvas and then use it as a pattern.
| | 06:07 | So the way I do that is I get a
reference to the patcanvas and its context and I
| | 06:14 | set the strokeStyle to
red and the lineWidth to 1.
| | 06:17 | I'm drawing a 1-pixel line from the top
left of that canvas down to the bottom right.
| | 06:22 | So I've got a diagonal red
line, and then I stroke it.
| | 06:25 | That way we get to the
actual drawing of the line.
| | 06:28 | So now I've done that.
| | 06:29 | I can use that canvas as a pattern.
| | 06:31 | So I have a variable here called
strokePat, and I tell my regular canvas to go
| | 06:35 | ahead and create a pattern out of the
patcanvas. And I'm passing in repeat.
| | 06:39 | Then I'm going to set the
strokeStyle--no fillStyle this time,
| | 06:43 | this time it's a stroke--to the strokePattern.
| | 06:45 | I am going to set the lineWidth
to be 25 to make sure it shows up.
| | 06:48 | And then I'm going to stroke a rectangle
with these dimensions, and it's going to
| | 06:52 | have a stroke width of 25.
| | 06:54 | So let's go ahead and save and let's
refresh, and you can see here is the little
| | 06:59 | source canvas over here, right, with its
red line in it, and you can see that when
| | 07:03 | I stroked the rectangle,
that pattern is now there.
| | 07:06 | Let's do the same thing in
Firefox, and we'll see it works.
| | 07:09 | All right, so we've seen three examples
of how to create patterns, using images,
| | 07:15 | video, and even another
canvas as our pattern source.
| | Collapse this transcript |
| Drawing with gradients| 00:00 | Creating gradients using the
HTML5 canvas is pretty easy.
| | 00:04 | There is two kinds of gradients:
| | 00:05 | there is linear and there is a radial.
| | 00:08 | The way you create gradients
is there are two steps involved.
| | 00:11 | First, you have to create the gradient
using the appropriate function to create
| | 00:16 | a gradient of the right type,
either linear or radial.
| | 00:18 | Now once you created the gradient, you
have to add color stops to the gradient
| | 00:22 | at certain positions in order to
create the necessary color transitions.
| | 00:27 | Once you've created the gradient,
it can be used anywhere a stroke or a
| | 00:30 | fill style can be used,
pretty much like patterns as well.
| | 00:34 | Let's take a look at how gradients work.
| | 00:35 | Linear gradients are defined along a path.
| | 00:38 | There is two points that
define a linear gradient.
| | 00:41 | The linear gradient then travels along that
path from the first point to the second point.
| | 00:47 | So in this example, we have a gradient
defined by the starting point x0, y0, and
| | 00:52 | the ending point, x1, y1.
| | 00:54 | In this case, we've got a light blue
color traveling along that line to the
| | 00:59 | lower-right point, x1, y1.
| | 01:02 | Radial gradients work a little bit differently.
| | 01:05 | Radial gradients are defined by two circles.
| | 01:08 | The radial gradient travels from the edge of
the inner circle to the edge of the outer circle.
| | 01:13 | And in this case, we've got the inner
circle of a darker blue color, and the
| | 01:17 | gradient travels from the edge of
the inner circle to the outer one.
| | 01:21 | To create gradients, you use
the createLinearGradient or
| | 01:24 | createRadialGradient functions.
| | 01:27 | The createLinearGradient function
takes four arguments, two points.
| | 01:30 | This is the first point.
| | 01:31 | This is the second point, which I
showed earlier, and that's the line that the
| | 01:36 | gradient travels along.
| | 01:37 | The createRadialGradient function takes
six arguments, which define the two circles.
| | 01:42 | The first circle is centered at x0, y0
and has a radius of r0. And the second
| | 01:47 | circle is at x1, y1 and has a radius of r1.
| | 01:50 | So that defines the two circles, which
define how the radial gradient travels.
| | 01:56 | Regardless of which gradient you create,
you use the addColorStop function to
| | 02:00 | add color stops at various positions.
| | 02:02 | The first argument, position, is a floating
point number going from 0 all the way up to 1.0.
| | 02:07 | You can kind of think of that as a percentage.
| | 02:10 | So, for example, a gradient at
the 80% position would be at 0.8.
| | 02:14 | You could add multiple color stops at
different positions, and you simply define
| | 02:18 | the color using any standard CSS
color string to create the color.
| | 02:23 | Let's go see gradients in action.
| | 02:25 | So I'm here in my code.
| | 02:26 | This is the gradients_start
file, and this is in chapter 06.
| | 02:31 | And now I'm going to go to my gradients
section in my snippets. That's right here.
| | 02:38 | So the first example we are going
to do is create a linear gradient.
| | 02:42 | So let's just copy this
example right here, and we'll paste.
| | 02:46 | We've got the call to createLinearGradient
right here, and this is the first point.
| | 02:56 | This is the second point.
| | 02:57 | Both of these points start at x
of 20 and go from y 20 to 280.
| | 03:02 | This is going to be a straight-line gradient,
and then we need to add some color stops.
| | 03:06 | We're going to go from red to
blue and then blue to green.
| | 03:08 | So at the 0 position, we're going to
start with red and then at the halfway mark,
| | 03:12 | we'll put blue in, and then we'll
end up with green at the 100% mark.
| | 03:18 | Then to display the gradient, we'll
simply set the fillStyle of the context to
| | 03:21 | the linear gradient we just created,
and then we'll fill the rectangle with the gradient.
| | 03:26 | So let's save, and let's go up and
look at the finished result, and you can
| | 03:31 | see that it worked.
| | 03:32 | So in this case, the linear gradient
is going from this point here straight
| | 03:36 | down to this point here.
| | 03:38 | Let's see what happens when
we change those two points.
| | 03:40 | So back here in the code, I'm going
to change this point here to be 220.
| | 03:47 | So now I've got x of 20, 20,
and the second point is 220, 280.
| | 03:53 | So we'll save, and we'll go
back to the browser and we'll refresh.
| | 03:58 | You can see now that I've got the gradient
going from the top left down to the lower right.
| | 04:04 | So that's pretty good for a
linear gradient. Let's try radial.
| | 04:10 | So let's go back to my snippets, and
now we're going to copy the code that
| | 04:16 | does the radial one. We'll copy and we'll paste.
| | 04:22 | All right, let's take a look at the code.
| | 04:29 | So in this case, I'm now creating a
radial gradient, and this is the first circle.
| | 04:34 | The first circle has its center
point at 525, 150 and has a radius of 20.
| | 04:39 | The second circle is centered at the
same location the first circle is but
| | 04:42 | has a larger radius, in this case 100.
| | 04:44 | So we've got two circles that are
centered at the same point, but of
| | 04:47 | just different radii.
| | 04:48 | So now we're going to add some
color stops to this gradient.
| | 04:51 | We're going to addColorStop and
we're going to do the same thing;
| | 04:53 | we're going to red to blue to green.
| | 04:55 | So red goes at 0, blue is at
halfway, green is at the 100% position.
| | 05:01 | We set the fillStyle to be
the gradient we just created.
| | 05:05 | And then we're going to just create an arc
that has the contents of the arc as the gradient.
| | 05:10 | So after setting the fillStyle, when you
call fill, it's going to fill it with gradient.
| | 05:14 | Let's save. Okay, let's go back to the browser and
we'll refresh, and you can see that we now
| | 05:20 | have a circle with the radial gradient.
| | 05:23 | So here is the inner circle right
here filled with red, and the gradient is
| | 05:26 | traveling from the edge of that
circle out to the edge of the larger one.
| | 05:31 | So let's go back to the radial gradient
definition and offset the circle a little bit.
| | 05:35 | So we'll go back to the code, and instead
of putting this circle at x of 525 and
| | 05:43 | 150, let's offset a little bit.
| | 05:45 | Let's put this one at y of 100 and
we'll put the x, let's say, at 500.
| | 05:51 | And this is going to cause the circle
to move up and to the left a little bit.
| | 05:56 | So let's save, back to the browser, refresh,
and you can see that the circle was here.
| | 06:02 | Now it's moved up here, and the gradient
is a little compressed over this way and a
| | 06:06 | little bit elongated this way.
| | 06:08 | So we've seen how to create linear and
radial gradients, and we've seen how to
| | 06:12 | add color stops and even change the
directions and origins of the gradients.
| | Collapse this transcript |
| Using clipping paths| 00:00 | The HTML5 canvas element gives
you the ability to create what are
| | 00:03 | called clipping paths.
| | 00:05 | You can think of a
clipping path as basically a mask.
| | 00:07 | It defines a region or a boundary
inside of which drawing will take place and
| | 00:12 | outside of which drawing will have no effect.
| | 00:14 | Now initially, the entire canvas is, by
default, the current clipping path, which
| | 00:18 | means anywhere you draw on the canvas,
as long as it's visible on the screen,
| | 00:22 | those bits are going to show
up to the user when you draw.
| | 00:25 | You can create a clipping path
using any path, and it's pretty easy.
| | 00:29 | There's just one function to do,
| | 00:30 | so you draw out a path normally,
and then you call the clip function, and
| | 00:33 | everything just works.
| | 00:34 | So imagine we had a photo that looks like this.
| | 00:36 | We applied a clipping path that looks like this.
| | 00:40 | So the white area is where the image
will show through, and the black area is
| | 00:43 | where the image will be blocked out.
| | 00:45 | If we were to draw this image on the
canvas using that clipping path, it would
| | 00:49 | look something like this.
| | 00:51 | So, only the part of the image
that's shown through the open area would
| | 00:54 | actually be drawn onto the canvas.
| | 00:57 | Now to do this, you use the clip function.
| | 00:59 | The clip function creates a new
clipping region by calculating how the current
| | 01:04 | clipping region intersects with the
area that's defined by the current path.
| | 01:09 | And then the new clipping region
simply replaces the current clipping region,
| | 01:12 | because each context can only
have one current clipping region.
| | 01:16 | Now, to do this in code, it
looks something like this.
| | 01:17 | Here is a canvas, and imagine you
have some code that looks like this.
| | 01:22 | So we define a path, and then we
make an arc, and then we call stroke.
| | 01:27 | That usually gives us a
circle that looks like this.
| | 01:29 | If we now go ahead and call the clip
function on the canvas context, now drawing
| | 01:35 | will only take place inside of that arc.
| | 01:38 | So let's take a look at this in code.
| | 01:40 | So here I am in the editor, and I've got my
snippets opened to my clipping paths region.
| | 01:45 | I'm going to go ahead and open
up my clipping_start example.
| | 01:50 | So here's what we're going to do.
| | 01:52 | First, let's go to the snippets,
and let's copy the first few lines over.
| | 01:58 | We'll copy that one, and we'll paste it in.
| | 02:01 | Then we'll scroll down a little bit,
and we'll get the drawImage call.
| | 02:07 | We'll copy that, and we'll paste that in.
| | 02:09 | So let's save, and let's see
how this looks in the browser.
| | 02:13 | So I'm going to bring up
clipping_start in the browser.
| | 02:16 | So you can see that the current
clipping region right now is the entire canvas;
| | 02:19 | nothing is being blocked out.
| | 02:20 | So the entire image is filling the canvas.
| | 02:25 | So let's go back to the code and that image,
by the way, is down here in the document.
| | 02:29 | So I'm just getting the image and
drawing it onto the canvas. We've seen this
| | 02:32 | already; nothing new here.
| | 02:34 | Let's go back to the snippets
and let's try creating a clipping path.
| | 02:37 | Let's start by making a circular clipping path.
| | 02:40 | This is what I just showed in the slides.
| | 02:44 | So I'm going to paste that in,
and I'm going to uncomment these two lines.
| | 02:49 | So before we run the code, let me point it out.
| | 02:52 | So this code is going to draw an
arc at the center of the canvas.
| | 02:55 | So we divide the Width by 2,
divide the Height by 2.
| | 02:58 | That gives the middle of the canvas.
| | 02:59 | It's got a radius of 150 pixels,
and it's a full and complete circle.
| | 03:04 | So that gives us a full circle in
the middle of the canvas, and then this
| | 03:07 | function call right here is the important one.
| | 03:09 | That creates a clipping
region out of the current path.
| | 03:12 | So let's go ahead and do that.
| | 03:14 | We'll save, and we're going to refresh.
And you can see that the results of that,
| | 03:19 | we have a circle in the middle of
the canvas, and only the part where the
| | 03:23 | circle is is where the image is being drawn;
the image is being masked out on either side.
| | 03:27 | So that's a pretty simple, easy example,
but let's make it a little bit more complex.
| | 03:32 | So let me go back to the code, and let's
go and comment these two lines out again.
| | 03:36 | Let's go back to the snippets.
| | 03:39 | Now, let's create an arbitrary clipping path.
| | 03:45 | So using what we already know and
have learned about creating paths can be
| | 03:50 | applied to clipping paths.
| | 03:51 | So here, we have a call to beginpath,
we have a series of lines, then we close
| | 03:56 | the path, and then we call clip.
| | 03:59 | So this is going to create a clipping
path out of just some arbitrary path that
| | 04:03 | I've made with a few line segments.
| | 04:05 | There's going to be four line segments:
| | 04:07 | one, two, three, and then
closePath will make the final one.
| | 04:11 | So let's save, and let's
click the Refresh button.
| | 04:14 | You can see that now the clipping
region has been changed to the four points
| | 04:18 | that I've created using a path.
| | 04:20 | So I took an ordinary path, didn't
stroke it--although I could if I wanted to--
| | 04:24 | and I made a clipping region out of it.
| | 04:26 | Let's see if it works in other browsers.
| | 04:28 | So let's go ahead and open this in say Firefox.
| | 04:33 | You can see, the result are the same.
| | 04:34 | So in this example, we saw how to
take ordinary paths and create clipping
| | 04:39 | regions, which are masks, through which
drawing can take place and outside of
| | 04:43 | which drawing is prevented.
| | Collapse this transcript |
| Drawing images and video| 00:00 | So using the HTML5 canvas element, you
can even draw images and video onto canvas
| | 00:05 | elements in the web page.
| | 00:07 | You can do this programmatically via JavaScript.
| | 00:10 | So using the image-drawing functions,
you can draw images in a variety of ways.
| | 00:14 | You can draw them from either an image
or a video element that's either in the
| | 00:17 | page or dynamically loaded, or from another
canvas element that's elsewhere in the page.
| | 00:24 | You can even resize or crop the
source image that's being drawn.
| | 00:29 | So let's take a look at
the image-drawing routines.
| | 00:32 | There are three ways to draw images.
| | 00:34 | The first one is the simplest.
| | 00:36 | drawImage takes a source image,
and the source image is either an image, a
| | 00:41 | video, or a canvas, and it draws that
image onto the destination canvas at the
| | 00:47 | point specified by dx and dy.
| | 00:50 | So that's the destination point
where the image will be drawn.
| | 00:53 | The second version drawImage again
takes the source image that you want to draw
| | 00:58 | and it draws it onto the destination
canvas at the location point dx and dy, but
| | 01:04 | it scales the image to fit into the
width specified by dw and the height by dh.
| | 01:11 | The last version of drawImage takes a
source image but also takes two sets of
| | 01:16 | arguments that specify how the source
and how the destination should be drawn.
| | 01:20 | It takes a source x and source y as
well as a source width and source height.
| | 01:25 | So you can actually draw only a portion
of the source image onto the destination
| | 01:30 | canvas at dx, dy, and the
given width and the given height.
| | 01:35 | So that sounds pretty complex.
| | 01:37 | It's probably a lot easier to see an
illustration of how each of these work.
| | 01:40 | So let's take a look.
| | 01:42 | The simple version of this
takes the image and dx and dy.
| | 01:46 | So you have the source image, and then
you have the destination canvas, and this
| | 01:50 | version just simply takes the source
image and copies it directly onto the
| | 01:54 | destination canvas at the dx, dy point.
| | 01:57 | The next version up from there takes
the image and draws at the location, but
| | 02:02 | optionally scales it.
| | 02:03 | So once again, you have the source image.
| | 02:05 | You have the destination canvas.
But in this case I've drawn the image onto
| | 02:09 | the canvas at the destination point. But in this
case it's been scaled to be a little bit larger.
| | 02:15 | You can also scale it to be smaller.
| | 02:16 | Now, the last example is
a little bit more complex.
| | 02:19 | So it takes the source image and
optionally a portion thereof and draws it onto
| | 02:26 | the destination canvas.
| | 02:28 | So here you have the source image
and the destination canvas right there.
| | 02:33 | But now, you've got only a portion
of the image that you are copying.
| | 02:36 | So you copy that portion onto the
destination canvas specified by the
| | 02:42 | arguments that you pass.
| | 02:44 | Let's take a look at these in action
and see how they work in the real world.
| | 02:48 | So here I am in my example.
| | 02:52 | This is the snippets, and I've
got my images_start file open.
| | 02:56 | So the first example I'm going to show is
just drawing an image directly onto the canvas.
| | 03:02 | So I'm going to copy, and I'm going to
come in here and I'm going to paste.
| | 03:08 | So what I'm going to do is get the
image element by using getElementById and
| | 03:13 | then just simply draw that
image right onto the canvas.
| | 03:16 | So let's scroll down here in the
document, and you can see that I've got this
| | 03:20 | image down here as well as a video,
and this is the source for that image.
| | 03:26 | And you can see that I've got both of these
elements are set to not display, so they
| | 03:30 | don't show up in the web page
when we have them in the browser.
| | 03:34 | So let's take a look at each one of these.
| | 03:36 | So, here are the images.
| | 03:38 | So this is the image I'm going to be using--
| | 03:40 | that's a nice little shot of Lake
Tahoe--and this video right here.
| | 03:44 | So I'm going to draw this video onto the canvas,
and it's just a basic video. So, that's that.
| | 03:51 | So let's take a look at the
first example. Scroll back up.
| | 03:55 | Again, pretty straight forward.
Just get the image and draw it onto the canvas.
| | 03:59 | So we'll save and you can see it works.
| | 04:02 | So the image is being copied
and then pasted onto the canvas.
| | 04:06 | Let's take a look at another example.
| | 04:08 | So for the next example, I'm going to
draw the image scaled down onto the canvas
| | 04:14 | using the second version
of the drawing routines.
| | 04:18 | So I'm going to get rid of this one
to avoid any competition. There we go!
| | 04:24 | Let's get rid of that comment.
| | 04:27 | So now this is the second version of
the drawImage function. So, same idea;
| | 04:31 | draw out in a location, but scale it down.
| | 04:33 | In this case, it looks like I am
going to scale it down by about half.
| | 04:36 | So I'll save and refresh.
| | 04:39 | We can see that that worked, and in
fact let's try it in another browser.
| | 04:46 | Let's open that in Firefox. Yup!
| | 04:48 | So that worked as well.
| | 04:49 | Let's go back to the code. All right!
| | 04:52 | So for the next example, now we're
going to draw just a portion of the source
| | 04:57 | image onto the destination canvas.
| | 05:00 | So I'm going to copy that, go
back to the sample, and paste.
| | 05:07 | So what we're going to do is specify
a rectangle that starts in the source
| | 05:13 | image--so we have the source image right here.
| | 05:14 | We're going to copy from this
portion of the source onto this part of
| | 05:20 | the destination canvas. So, let's save.
| | 05:23 | What we're going to do is
just get a copy right here.
| | 05:26 | This little island is going to be what's
taken out of the source image and drawn.
| | 05:31 | So we refresh.
| | 05:33 | We can see that that's what happened.
| | 05:35 | Let's go back to Firefox,
do the same thing, Refresh.
| | 05:38 | You can see that in both cases a
portion of the source image was essentially
| | 05:43 | cropped and drawn into the
destination canvas. And then for the last example,
| | 05:49 | let's actually draw some video.
| | 05:50 | Now, drawing video is a little bit
challenging because you can't just simply say, hey,
| | 05:56 | draw this video.
| | 05:57 | The drawImage function is going to
draw whatever the current playback
| | 06:03 | frame happens to be.
| | 06:04 | So here's how we need to do this.
| | 06:06 | First, let's scroll down.
| | 06:09 | So, here's the video.
| | 06:10 | The video tag is right here.
And you can see that it's set to loop, and
| | 06:14 | it's currently hidden.
| | 06:15 | It's also not playing.
| | 06:16 | There's no auto-play in here.
| | 06:18 | So what we are going to do is get the
video element, tell the video element to
| | 06:25 | go ahead and play, and then we're
going to set a interval function, which is
| | 06:29 | going to be called every 16 milliseconds.
| | 06:32 | So every 16 milliseconds, we're
going to get the canvas, get the drawing
| | 06:37 | context, and get the video element,
and then we're just going to draw the image
| | 06:42 | from the source video directly onto the canvas.
| | 06:45 | So this will grab each frame as it's
being played, every 16 milliseconds,
| | 06:48 | and draw the video. So let's save.
| | 06:51 | Let's refresh.
| | 06:55 | So what's happening is the video
element is actually down here, and this is the
| | 06:57 | canvas. But the interval function is
being called every 16 milliseconds which
| | 07:01 | gives us the frame rate that's
needed to play the video back.
| | 07:04 | So let's try it out in Safari because we
haven't picked on Safari yet, and we can
| | 07:11 | see it's working in Safari as well.
| | 07:13 | So, what have we seen?
| | 07:14 | We've seen ways to draw images onto the
canvas, and we've seen ways of drawing
| | 07:19 | source portions of the image.
| | 07:21 | We've seen how to resize images, and we
even saw how to take video content from
| | 07:26 | a video element and play it back on a canvas.
| | Collapse this transcript |
|
|
7. Advanced Canvas Drawing OperationsTransforming objects using the translate tag| 00:00 | In this chapter, we're going to look at
some pretty advanced canvas operations,
| | 00:03 | and in fact some of these are not
necessarily routines or features that cause
| | 00:08 | any drawing to happen, but they
certainly do have a profound effect on the
| | 00:12 | results of drawing operations that you
learned about earlier on in the course.
| | 00:16 | And so we're going to start off
by looking at transformations.
| | 00:20 | Transformations are essentially a way
that affect how objects are drawn to the
| | 00:24 | canvas to achieve some pretty common,
but yet difficult to program, effects.
| | 00:30 | There's three basic
transformations that the canvas provides.
| | 00:33 | There's translate, scale and rotate,
along with a way to define your own
| | 00:39 | free-form transforms.
| | 00:42 | Transforms affect all of the drawing
operations that come after them, and they are additive.
| | 00:49 | Each transform is added to
the effects of the previous one.
| | 00:54 | So just like other global canvas
properties, like line width and so on,
| | 01:00 | transforms affect everything.
| | 01:01 | You define a transform, you
use it, and then you perform some
| | 01:05 | drawing operations.
| | 01:06 | Now, because they are additive, this is
where saving and restoring the canvas
| | 01:11 | state can really come in handy.
| | 01:12 | Let's start by taking a look
at the translate transform.
| | 01:17 | It's the simplest one to use, and all it
really does is moves the canvas origin
| | 01:22 | to a new location. And the way you do
it is by calling the translate function
| | 01:27 | with an amount to move the origin in
the X direction and an amount to move the
| | 01:33 | origin in the Y direction.
| | 01:35 | So let's imagine for a moment you have
a canvas and at the upper left of the
| | 01:38 | canvas, that's the current
origin point. That's where 0,0 is.
| | 01:42 | If you use the translate function to
move the origin by an amount X and Y, then
| | 01:48 | all you have done is move
the location of the origin.
| | 01:53 | So now, anything drawn at 0,0 will
be drawn at this point on the canvas
| | 01:58 | instead of this point.
| | 02:00 | So let's take a look at how that works.
| | 02:01 | I'll go into the code.
| | 02:03 | So here we are in my editor, and
in the snippets file, I'm under the
| | 02:08 | Translate Transform section.
| | 02:10 | So let's open up our example, and we're
going to go to the Advanced folder, and
| | 02:16 | we're going to go to the
translate_start example.
| | 02:21 | So what we're going to do is copy some
code, and we're going to come in here and
| | 02:25 | copy this over, copy, and we're going to paste.
| | 02:32 | So before I show you what the example
does, let me just comment out this call
| | 02:36 | to translate, and we will save and we will
go over the browser and look at the results.
| | 02:41 | So, let's bring this up.
| | 02:43 | So you can see that I'm drawing a blue
rectangle at the origin point 0,0 right here.
| | 02:48 | So if we go look in the code, you
can see that there it is. It's at 0,0.
| | 02:54 | It's 100 pixels wide and 50 pixels high.
| | 02:57 | Now, if I uncomment the call to
translate, what I'm doing here is calling
| | 03:03 | translate and I'm getting the width of
the canvas and dividing it in half, and
| | 03:07 | I'm getting the height of the
canvas and dividing it in half.
| | 03:10 | So this will pretty much move the origin
of the canvas right to the middle, half
| | 03:17 | the width and half the height.
| | 03:18 | So when I call fillRect again, even
though I'm calling it to draw at the 0,0
| | 03:24 | location, the origin has now been
moved to the middle of the canvas.
| | 03:28 | So the second rectangle will be
drawn at the middle point of the canvas.
| | 03:33 | So let's save, and let's go back
to the browser, and let's refresh.
| | 03:38 | So you can see, I've got two
rectangles. They are both drawn at 0,0.
| | 03:43 | But in the first example, 0,0 is
up here, and then after the call the
| | 03:46 | translate, 0,0 moves to here.
| | 03:49 | So this can be pretty useful when you
are creating a whole bunch of objects to
| | 03:53 | be drawn on the canvas at different
locations and the results of those
| | 03:57 | locations are arrived at via
various calculations and so on.
| | 04:01 | Rather than having to keep track of
all of those points, you can just simply
| | 04:04 | move the origin to where you need it to
move to, do your drawing, and then set
| | 04:08 | it back to its previous state.
| | 04:10 | So in this example, what we've seen is how
to use a basic translate transform to
| | 04:15 | move the origin around and
affect where objects are drawn.
| | Collapse this transcript |
| Scaling objects with the scale transformation| 00:00 | The scale transformation causes drawing
operations to be multiplied by a scale
| | 00:06 | factor in the X and Y directions.
And you can scale operations in the X and Y
| | 00:14 | directions independently.
| | 00:15 | You can provide a scaling
factor for X and a scaling factor for Y.
| | 00:19 | So the way that scale transformation
works is pretty simple. So suppose I had a
| | 00:24 | rectangle that was 20
pixels wide and 10 pixels high.
| | 00:29 | Well, if you put that through a scale
transform and I pass in say a factor of
| | 00:34 | 2 for both the X and the Y direction,
the result of that would be, if I call
| | 00:40 | the same function, even though I said
fill the rectangle with 20 pixels wide
| | 00:44 | and 10 high, because of the scale
factor, this would be 40 pixels wide and 20
| | 00:49 | pixels high. So let's take a look
at that in code and see how it works.
| | 00:53 | So here I am in the code editor,
and I've got my Scale Transform section of my
| | 00:58 | snippets. So let's open up our scale example.
| | 01:04 | So here is our scaling code.
| | 01:06 | Let's go back to the snippets. So I'm
going to copy this guy over and paste.
| | 01:18 | So, a couple of things I want to point out.
| | 01:20 | First, I'm using the blue fill style to
fill the rectangle at the 0,0 location.
| | 01:26 | So what I'm going to do now is perform a scale
transform and draw the same size rectangle
| | 01:32 | again, only at a different location.
| | 01:35 | So here you can see the
width and the height of the same.
| | 01:37 | I'm just offsetting this
rectangle so we can see it.
| | 01:40 | I'm also using the save and restore in
order to save the drawing context of the
| | 01:46 | canvas and restore it after doing any drawing.
| | 01:50 | So let's save. Let's go out to the
scale_start. So you can see, here is
| | 01:55 | the rectangle, right.
| | 01:56 | Here is the first one.
Here is the second one.
| | 01:58 | Now they're both being told to draw at
the same size, but because of the scaling
| | 02:02 | factor, this one is larger.
| | 02:04 | So let's take a look at where save
and restore canvas state come in handy.
| | 02:09 | So suppose these weren't here, and
suppose I had another call to scale, only in
| | 02:17 | this case I want to scale things down.
| | 02:20 | So I would say, instead of 1.50.5--
and let's change this one to 0.5 as well, and
| | 02:29 | I'll do the same thing with the
fillRect, and in fact I'll offset this one a
| | 02:33 | little bit--325--so we can see it.
| | 02:36 | Now let's go over to the canvas and see
what happened. We'll refresh. Actually, I
| | 02:41 | should probably move it a little bit more.
| | 02:48 | So you can see that the scale factor is
not really affecting this the way that
| | 02:54 | we'd expect it to, because what's
happening is I'm first doing a scale-up and
| | 02:59 | then a scale back down.
| | 03:00 | If I put save and restore around
this, watch how that changes things.
| | 03:11 | Now we save, and then we go
back out. Now let's refresh.
| | 03:18 | See, now things are really being shrunk down.
| | 03:21 | So what was happening was, since I
was calling this scale function after this
| | 03:27 | one--remember, transforms are additive.
| | 03:29 | So I go from a scale factor of 1 to a
scale factor of 1.5 and then 2. Then I go
| | 03:37 | to scale factor of a half.
| | 03:39 | Well, that only cuts this scale
factor in half, not the original one. But by
| | 03:44 | putting the save and restore around it,
this scale function operates on the
| | 03:49 | drawing context's regional scale factor,
which is 1 and 1 in both the X and Y directions.
| | 03:55 | So now we've seen how to use a scale
transform and we've even seen how to use
| | 04:00 | save and restore to save the canvas's
drawing context so that transforms don't
| | 04:05 | interfere with each other.
| | Collapse this transcript |
| Rotating objects with the rotate transformation| 00:00 | Rotate transforms cause subsequent drawing
operations to be rotated by a given angle.
| | 00:06 | And remember, whenever we say angle
in canvas, we're talking about radians;
| | 00:09 | we're not talking about degrees.
| | 00:11 | It's also important to note that
rotation takes place around whatever the
| | 00:15 | current origin of the canvas is, not the
center of an object that you're about to draw.
| | 00:21 | If you want to rotate around an object's
center, or for that matter around any
| | 00:26 | point on a particular object, you should
use the translate transform to move the
| | 00:31 | origin to the object center or
whatever point you want to rotate around, then
| | 00:35 | rotate, and then translate the origin back.
| | 00:38 | The rotate transform just takes one
argument, and that's the angle argument.
| | 00:43 | The angle specifies the amount to
rotate the drawing operations that come after
| | 00:48 | you set the rotation transform.
| | 00:50 | Remember, that's radians, it's not degrees.
| | 00:52 | So let's jump over to the
code and take a look at rotate.
| | 00:56 | So I've got my Rotate Transform
snippets up here, and let's open up the rotate
| | 01:03 | example. So, a couple of examples to show.
| | 01:08 | First, let's do the simple one.
| | 01:10 | We'll copy and we'll paste.
| | 01:16 | So what I'm doing here is causing the
fillStyle of the context to be blue, and
| | 01:22 | I'm going to fill a rectangle at 153, so
X is 150, Y is 30, and the rectangle is
| | 01:29 | 100 pixels wide and 50 pixels high.
And then after that I'm going to rotate by
| | 01:34 | half a radian and then draw the same
rectangle again at the same location.
| | 01:39 | So let's save and let's
bring this up in the browser.
| | 01:44 | So you can see that what happened was
the first rectangle was drawn with no
| | 01:48 | rotation. The second rectangle, however,
was rotated by half of the radian in
| | 01:53 | the clockwise direction. And you can
see that if you were to draw a straight line
| | 01:58 | from the top of this rectangle, it
would go almost to where the origin is,
| | 02:02 | pretty much the same point that
this one is pointing out right here.
| | 02:05 | So rotation did not take place
around the center of the object;
| | 02:08 | it took place around the origin up here.
| | 02:11 | So if we wanted to say rotate an object
around the center of itself, we'd have to
| | 02:17 | first change the origin to the
center of the object, then rotate it.
| | 02:22 | So let's go back to the
code and see if we can do that.
| | 02:23 | So let's go back to the snippets,
and let's take this example.
| | 02:30 | We'll go back to the rotation. So we'll get rid of
this one, and we'll replace it with a new one.
| | 02:37 | Let's take a look at what's going on here.
| | 02:38 | So I'm actually combining two different
transforms here to achieve a particular effect.
| | 02:45 | So I start out by translating the origin
from the upper-left corner to the exact
| | 02:52 | middle of the canvas.
| | 02:53 | So I divide the width in half, divide
the height in half. That gives me the
| | 02:56 | middle. Then I calculate a radian
equivalent to a 20-degree rotation.
| | 03:02 | Then I have this for loop, which
start at 0, goes to 3600, and increments the
| | 03:09 | degrees by 20 degrees each time.
| | 03:12 | So I've divided this up into a
certain number of steps, in this case 18,
| | 03:17 | and each time we step, we're going to rotate
by this radian, which is a 20-degree rotation.
| | 03:23 | We're going to stroke a line each time,
so let's see what that looks like.
| | 03:27 | So I go back over here and I refresh,
and you can see what's happened is the
| | 03:32 | original line that I drew right here,
has been rotated around itself in a series
| | 03:37 | of 18 steps, 20 degrees each time.
| | 03:40 | So again, what's happening is I've
translated to the middle of the canvas.
| | 03:46 | Then I have a call to move to, which moves
me 100 pixels negative, which means it moves
| | 03:52 | me to the left in the X direction,
and then I lineTo 100 in the positive X
| | 03:58 | direction. So I'm creating a
200-pixel-long line centered about whatever the
| | 04:03 | current origin is, which is in the
middle of canvas, but it's rotated each time.
| | 04:07 | Each time to this for loop, I'm
rotating by an additional 20 degrees.
| | 04:10 | That's this radian right here.
| | 04:12 | So for 18 steps, we rotate, and that's what
causes each subsequent draw of the line to
| | 04:18 | be drawn through the new
origin but rotated each way.
| | 04:22 | So this example shows us how to use
two transforms together to achieve an
| | 04:25 | effect, as well as using the rotate
transform to rotate objects around the
| | 04:30 | origin of the canvas.
| | Collapse this transcript |
| Applying a custom transformation| 00:00 | The last transform we're going to
take a look at is the custom transform.
| | 00:03 | Now in addition to the transforms
that are built into the canvas, you can
| | 00:06 | also define your own.
| | 00:09 | Transforms are defined as a matrix.
| | 00:12 | A matrix has the format that you see here.
| | 00:14 | There are six variables.
| | 00:15 | There is a, b, c, d, e, and f. And to
use a transform, a new point is found
| | 00:22 | by applying that transformation matrix to
each point in the image that's being transformed.
| | 00:29 | Now, you don't need to panic.
| | 00:31 | I'm not going to make you learn matrix
math, but this does come in handy when
| | 00:35 | you want to apply a transformation
that is not built into the canvas.
| | 00:39 | So, for example, canvas gives you
transforms for rotation, scaling, and
| | 00:44 | translating, but there are plenty of
other transforms out there that you might
| | 00:47 | want to use, and since they are not
built in, you would have to use a matrix
| | 00:50 | like this to define one.
| | 00:52 | So we'll see examples of that in a
moment, but the way that you apply a custom
| | 00:55 | transform is by using one of
the two transform functions.
| | 01:00 | The first one is simply called
transform, and it takes these six arguments, which
| | 01:04 | correspond to the variables
you see in this matrix here.
| | 01:07 | The transform function takes the
transform you're defining here and adds it to
| | 01:12 | whatever the current
transform of the canvas currently is.
| | 01:17 | So if the canvas already has a
transform, like a rotation or a scale or a
| | 01:21 | resulting transform from a series of
transforms that came before it, then this
| | 01:25 | one will simply be added to that one,
| | 01:27 | because remember, transforms are additive.
| | 01:29 | The second one is called setTransform,
and it takes the same six arguments.
| | 01:34 | The main difference between
setTransform and transform is that setTransform
| | 01:39 | resets the canvas to be what's
called the identity transform, which is a
| | 01:44 | transform that just doesn't do anything.
| | 01:46 | So in other words, it erases all the
previous transforms and then applies the
| | 01:51 | one you're defining here.
| | 01:52 | So this one is additive.
| | 01:54 | This one is not additive.
| | 01:56 | This one resets the canvas and then
apply the transform that you're defining.
| | 02:00 | Let's take a look in the code
to see how this stuff works.
| | 02:04 | So here I am in the code.
| | 02:05 | I've got my snippets file open, and I'm
at the custom transform area, so let's
| | 02:11 | open up our custom transform example.
| | 02:14 | It's called transform_start.
| | 02:16 | Let's do something simple
that we've already seen before.
| | 02:20 | So, let's first copy these two
lines, and we'll paste those in.
| | 02:25 | Now, you've seen this already.
Basically, we just take a blue rectangle and put
| | 02:29 | it on the canvas, so let's just make sure
that that works, and it does work. That's good.
| | 02:33 | All right, so let's go back to the code.
| | 02:35 | What we're going to do now is recreate the
translate transform using our custom transform.
| | 02:43 | So we'll copy this and we'll paste
it over, and I'll explain how it works.
| | 02:48 | So a translation matrix for a
translate transform looks like this.
| | 02:53 | Those six variables are right here.
And the first row is 1 0 and then the amount
| | 02:59 | you want to translate the x by,
and then the second row is 0 1 and the amount
| | 03:04 | you want to translate y by.
| | 03:05 | So remember, the variables go in the
order of a, b, c, d, e, and f. So let's
| | 03:11 | define that transform.
| | 03:12 | We're going to make the new rectangle
red, so that's the fillStyle there.
| | 03:16 | Just like in the translate example,
we're going to translate the rectangle to
| | 03:20 | the center of the canvas.
| | 03:22 | So tx is going to be the width of the
canvas divided by 2. The y will be the
| | 03:26 | canvas height divided by 2--
| | 03:27 | that gives us the middle of the canvas.
And then instead of using the translate
| | 03:31 | function, we're just going to call the
transform function, and we pass in 1, 0--
| | 03:35 | that's these two right here--then 0, 1--that's
these two right here--and then tx and then ty.
| | 03:41 | That will add this translate
transform to the canvas, then we'll fill the
| | 03:46 | rectangle, and then we'll call the
reverse transform, which translates us back
| | 03:51 | to the upper left of the canvas--just in
case we had any drawing that came after this.
| | 03:57 | So we save and then let's go to the
browser and let's refresh. And you can see
| | 04:02 | that the blue rectangle is drawn at 0, 0.
The red rectangle is also drawn at 0,
| | 04:07 | 0, but the new origin has now
been translated to right there.
| | 04:11 | So that seems to have worked fine.
| | 04:12 | Let's go back to the code.
| | 04:13 | So you can see right there, even
though the rectangle is placed at 0, 0,
| | 04:17 | because of the translation, the origin
was moved to the middle of the canvas.
| | 04:21 | Let's create a new transform.
| | 04:23 | So now we're going to go back to snippets,
and we're going to copy this example.
| | 04:27 | Okay, so we copy and we'll
come over here and we'll paste.
| | 04:34 | In this example, we're going to
create what's called a skew transform.
| | 04:38 | Now a skew transform--sometimes it's
called a shear transform--and in this case
| | 04:42 | we're going to have a green rectangle
and we're going to shear the objects using
| | 04:46 | various directions x and y. So, a skew
transform is defined by the number 1 and
| | 04:52 | then the amount you want to skew in the
y direction, then the amount you want to
| | 04:55 | skew in the x direction, the number 1
here, and then these two are left at 0.
| | 05:00 | So we're going to use a green rectangle
for this one. And the skewing factor is
| | 05:03 | defined by a multiplication factor, so
I'm going to multiply by 0.2 in the x
| | 05:07 | direction and I'm going to
leave the y direction alone.
| | 05:10 | Now in this case, I'm going to use the
setTransform function, and remember, this
| | 05:14 | resets whatever the transform is
that's currently on the canvas.
| | 05:19 | So, I don't have to worry about any
transforms that came before me. And then
| | 05:23 | we're going to fill the rectangle at
this location, the point 250 by 20, and it
| | 05:28 | will be 100 wide and 50 high.
| | 05:30 | So let's save, and let's go back
to the browser and let's refresh.
| | 05:36 | You can see now that I've drawn a
green rectangle that's been skewed in the X
| | 05:40 | axis direction, so it's
been sheared a little bit.
| | 05:43 | Let's make some changes and see how
that works. Let's go back to the code.
| | 05:46 | I can increase the amount of shear. I can say
this is 0.4, and let's refresh the browser now.
| | 05:53 | You can see that the shear
amount got a little bit more.
| | 05:55 | All right, let's try it in the y direction.
| | 05:58 | So I'll set this to 0, and we'll make
this 0.3 and we'll save and we'll refresh.
| | 06:05 | And you can see that this time the
rectangle got sheared in the Y axis.
| | 06:10 | Now what we have done here is create a
new transform that is not built into the
| | 06:14 | canvas. And just for good measure,
let's make sure it works in other browsers.
| | 06:19 | So we'll bring this up in Firefox, and
you can see, the effect is the same.
| | 06:26 | Let's bring it up in Chrome, and you
can see the effect is the same there, too.
| | 06:33 | So what we have learned here is how
to use the custom transform matrix to
| | 06:37 | recreate a transform we already know how
to use, but we also saw how to create a
| | 06:41 | new transform that's not built into the canvas.
| | 06:45 | You can look up all kinds of transform
matrices on the Internet and just plug in
| | 06:49 | the values into that transform function.
And doing so, you can create transforms
| | 06:54 | that are not built into the canvas
that you can use in your own drawings.
| | Collapse this transcript |
| Compositing in Canvas using globalAlpha| 00:00 | In this section we're going to talk
about the canvas compositing methods and the
| | 00:03 | global alpha setting.
| | 00:05 | The canvas context has a setting for
what's called the global alpha, and that's
| | 00:10 | the opacity setting that affects all of the
drawing operations that happen on the canvas.
| | 00:13 | There's also a setting for what's called
the default compositing method, and that
| | 00:19 | affects how new content is drawn
onto the canvas surface and how it is
| | 00:23 | potentially affected by the
content that's already there.
| | 00:27 | Now, to use the global alpha, you simply
set the context.globalAlpha property to
| | 00:31 | a value from 0.0 to 1.0.
| | 00:34 | The default being 1.0, which means full opacity.
| | 00:37 | Now there are 12 different
compositing methods, and I've illustrated them
| | 00:41 | here for you to look at.
| | 00:43 | The first is called
source-over, and this is the default.
| | 00:47 | Basically, what that means is every
time you draw something new, it gets drawn
| | 00:51 | on top of what's already there, which
is pretty much the behavior you'd expect.
| | 00:55 | Each time you draw a new shape, you'd
just expect it to appear on the canvas,
| | 00:59 | on top of everything that came before it.
| | 01:01 | The next one is source-in.
| | 01:02 | You can see that what's happening is
the drawing is only taking place where
| | 01:07 | there's already content on the canvas.
| | 01:10 | So in this case, the green rectangle is
only showing up where there are already
| | 01:13 | portions of the blue rectangle.
| | 01:15 | Source-out is just the opposite.
| | 01:18 | The newly drawn object, the green
rectangle, is only showing up where the blue
| | 01:22 | rectangle is not, where they don't overlap.
| | 01:25 | The source-atop is kind of like
source-in, except that it leaves the original
| | 01:31 | content in its place.
| | 01:32 | The source-in left only the new content;
source-atop leaves the old content plus
| | 01:38 | the intersection of
whatever the new content was.
| | 01:41 | The lighter compositing method takes
a look at the intersection of the new
| | 01:45 | content and the old content, draws the
pixels in a lighter color of what they
| | 01:50 | would have been normally.
| | 01:52 | The xor or exclusive or drawing
operation, or compositing method, takes the new
| | 01:58 | content, intersects it with the old content,
and then clears the area where the two overlap.
| | 02:04 | The second row shows some other operations.
| | 02:07 | The destination-over is kind of like
source-over, only that the new content is
| | 02:12 | drawn, but it's clipped by what's already there.
| | 02:15 | Then there's destination-in, which
is kind of the opposite of source-in.
| | 02:19 | In this case, only where the two
overlap is the content drawn, but the new
| | 02:24 | content is left out and the old content is kept.
| | 02:27 | In destination-out, that's the
opposite of destination-in, so wherever the
| | 02:31 | two don't intersect, that stuff is left,
but all the other content is removed from the canvas.
| | 02:36 | Destination-atop is the opposite of source-atop.
| | 02:41 | In this case, the new content is kept,
along with whatever the old content was,
| | 02:46 | as long as it intersects with the new content.
| | 02:48 | Darker basically says draw the new
pixels but make them darker instead of lighter.
| | 02:53 | And then copy means just draw the new content;
| | 02:57 | anything that was already on the
canvas is removed and only the new drawing
| | 03:00 | operation is what wins.
| | 03:02 | So let's go over to the
code and see these in action.
| | 03:05 | So here I am in the code and on the
snippets I've got my Global Alpha snippet.
| | 03:10 | So let's go ahead and copy this over.
| | 03:15 | First, I want to copy a bunch of
definitions, and what I'm going to do is
| | 03:18 | paste that in here.
| | 03:19 | Okay, so I've got my globalAlpha.
| | 03:22 | It starts off at 1.0, and that's the
default value, but we're just going to set
| | 03:25 | it anyway for purposes of illustration.
| | 03:28 | Then I have an array of rectangles.
So, I've got 1, 2, 3, 4, 5, 6, 7,
| | 03:32 | I've got 8 rectangles all defined at
different locations. They overlap each other.
| | 03:38 | So let's go ahead and get to drawing.
| | 03:40 | I'm going to copy that in.
| | 03:45 | So this for loop will loop over
this array of rectangles and draw each
| | 03:51 | rectangle on the canvas.
| | 03:53 | So for the moment, I'm
going to comment this line out.
| | 03:55 | So you can see that the
rectangles are being drawn.
| | 03:57 | There's a blue one and a red one.
| | 03:59 | I'm drawing them down the canvas here.
| | 04:01 | So let's go put that line back in.
| | 04:02 | So each time through the loop, the
globalAlpha is going to be reduced by 0.3.
| | 04:07 | So let's see what effect that has.
| | 04:10 | The opacity changes, for each time
through the loop and the drawing operations
| | 04:14 | get lighter and lighter.
| | 04:16 | Just to make sure that that works cross
browser, let's go ahead and open this up in.
| | 04:21 | let's say Firefox. Sure enough, it works.
| | 04:23 | Now, let's take a look at
some compositing operations.
| | 04:26 | So I'll go to my snippets and
here's my Compositing example.
| | 04:35 | Copy this and paste it in.
| | 04:37 | So one of the things that I want to
point out here is that because some of these
| | 04:41 | drawing operations affect the current
canvas content, what I've done is made a
| | 04:47 | whole row of separate
canvases to show each example.
| | 04:51 | So I've got two rows of six canvases,
each one is 150 x 150, and we're going to
| | 04:58 | draw in each one of those guys.
| | 05:00 | So here are all the compositing methods as
strings--source-over, source-in and so on.
| | 05:06 | All 12 of them are there.
| | 05:07 | I've got two rectangles, and each one of
these rectangles is going to be drawn in
| | 05:13 | each one of the canvases.
| | 05:16 | So, I have an index variable that's
going to keep track of what compositing
| | 05:20 | method we're currently
drawing, and then I have a loop.
| | 05:23 | So I'm going to start at 0, loop over
the array of compositing methods. Each
| | 05:27 | canvas is identified by
the name canvas + an integer.
| | 05:31 | So you can see there is
canvas1, canvas2, canvas3.
| | 05:34 | So I'm going to get each canvas, get its
drawing context, and draw two rectangles:
| | 05:38 | one blue and one green.
| | 05:40 | So I'm going to draw the first rectangle,
then set the composite operation right
| | 05:44 | there, to whatever the composite method
is, and then fill the second rectangle.
| | 05:49 | So let's go ahead, save this.
| | 05:53 | Let's go back to the folder
here, fire up compositing_start.
| | 05:57 | You can see that each one of the
rectangles is being drawn, and we are getting
| | 06:03 | the same results for the
compositing method as I showed in the slides.
| | 06:08 | Let's go over to Firefox and see
how it looks there. It looks pretty good.
| | 06:13 | And just for good measure, let's try
it out in Chrome as well. Looks right.
| | 06:21 | So in this example, we saw how to use
compositing methods, we saw how to use the
| | 06:25 | global alpha to affect drawing
operations, and we can see how we can draw content
| | 06:29 | onto the canvases using a variety
of methods that affect the source and
| | 06:34 | destination content.
| | Collapse this transcript |
| Manipulating raw pixels| 00:00 | Probably one of the coolest and most
powerful features of the HTML5 canvas is
| | 00:05 | that your script can now get access
to raw pixel data on the canvas and
| | 00:11 | manipulate the pixels directly.
| | 00:13 | You can access the individual pixel
data as an array of bytes on the canvas.
| | 00:19 | Then this data can then be
manipulated and put back into the canvas.
| | 00:24 | Every image in a canvas, and in fact
this is true of all canvas content, is
| | 00:30 | composed of four-byte-wide pixels.
| | 00:33 | So let's imagine we had a picture like this on
the canvas and we looked at an individual row.
| | 00:39 | So that individual row would be made
up of pixels, starting at the left-hand
| | 00:43 | side over here and
continuing all the way over to here.
| | 00:46 | Imagine each pixel is a
little box going across the row.
| | 00:49 | Well, each one of these pixels is
made up of a four-byte combination.
| | 00:54 | There's a red, green, and blue component
of that pixel along with the alpha setting.
| | 01:00 | So by getting access directly to these
bytes, we can manipulate how the image
| | 01:06 | looks in the canvas.
| | 01:08 | So if we were to calculate the size of
that image data array, it would be the
| | 01:13 | height of the image, right, so this
height here, times the width, times four--
| | 01:17 | because remember each one of
these pixels is four bytes wide.
| | 01:20 | So to get the number of bytes, you'd
multiply the height, times the width, times
| | 01:24 | four to account for the four
bytes that make up each pixel.
| | 01:29 | Now one of the things I should point out
here is that this is an obvious security issue.
| | 01:34 | If any willy-nilly script could just get
access to the image data on a canvas, it
| | 01:40 | could surreptitiously send it back to
another web site or another web server.
| | 01:45 | So, for security reasons scripts
have to come from the same origin.
| | 01:50 | If a script wants to try to access the
content of a canvas on the web page,
| | 01:54 | then the script had to have come from
the same origin as the web page itself;
| | 02:00 | otherwise, it is denied access and the
browser raises a security exception.
| | 02:05 | So what are the functions
for accessing image data?
| | 02:09 | Well, we have a couple things we can do.
| | 02:11 | We can get the width and
height of the canvas pixel data.
| | 02:15 | There is also a data property, which is a
single-dimension array of all the raw pixel data.
| | 02:22 | This is the big array that
has all the bytes of the image.
| | 02:26 | We can create new image data from scratch.
So this is createImageData. There are two versions.
| | 02:32 | One takes a width and a height; the
other one takes an existing image data
| | 02:36 | structure and creates a new one from it.
| | 02:38 | We can also get image data, and we can
get image data within the given bounds.
| | 02:43 | So starting at the source canvas, we can
start at source x and source y point and
| | 02:49 | given a width and a height, we can
get a portion of the image data.
| | 02:53 | We can then do whatever we want
with the image data and put it back
| | 02:56 | using putImageData.
| | 02:58 | Now putImageData puts the modified
image data specified by image data back into
| | 03:03 | the image at point dx and dy.
| | 03:06 | These arguments here--dirtyDx,
dirtyDy, dirtyW, and dirtyH--
| | 03:12 | these are all optional and they
specify what's called a dirty rectangle.
| | 03:17 | Now if a dirty rectangle is
supplied, then only the bits inside that
| | 03:21 | rectangle are updated.
| | 03:23 | So let's take a look at a real-life
example of using the image data access.
| | 03:28 | So here's my code, and here in my snippets
| | 03:31 | I've got my rawdata example,
and here's my rawdata file.
| | 03:36 | Now, one of the things I want to point
out is that I'm running this from a web
| | 03:40 | server that happens to be located on my machine.
| | 03:44 | So here you can see in the browser,
I've got localhost accessing this file.
| | 03:48 | Again, that's so that the browser has a
domain to go off of when it's running my
| | 03:53 | script code and trying to access the image data.
| | 03:56 | So if you want to see this example work,
all you need to do is run it from a
| | 03:59 | real web site. It doesn't matter if
it's localhost or whatever web site you
| | 04:02 | usually work on; you can just simply run this
by loading up the local file in the browser.
| | 04:07 | So let's go back to the code.
| | 04:09 | So let's go to the snippet, and what I'm
going to do is copy this first example here.
| | 04:17 | So, let's scroll down a little bit.
| | 04:21 | Here is the source image that I'm going to be
manipulating, and it is this image right here.
| | 04:29 | So what I'm going to do
is go back to the source.
| | 04:34 | So what we are doing is getting the
element out of the document, and then we're
| | 04:38 | going to simply draw the image onto the canvas.
| | 04:41 | So let's make sure that that works first.
| | 04:43 | So let me refresh. Okay, so that's working.
| | 04:45 | So we're taking the source image, drawing
it onto the canvas, and everything is fine.
| | 04:49 | That's no big deal;
| | 04:50 | we've already seen that before.
So let's go back to the code.
| | 04:52 | So, let's do something
interesting to this image.
| | 04:56 | Let's get the image data and
do some manipulation to it.
| | 05:05 | Paste. So let's take a look at what
the code does that I just copied in here.
| | 05:10 | What we're going to do is get the
image data and every 15th row of the image
| | 05:15 | we're going to convert into a five-
row-high strip of inverted pixels.
| | 05:22 | So we're going to take whatever
the pixel value is and invert it.
| | 05:28 | I've got a couple of variables here.
| | 05:31 | I've got a variable that's tracking the
current row, and I'll start it for row 0.
| | 05:35 | And then I have the maximum row,
which is the same as the canvas height.
| | 05:39 | Then I get the image data by calling
the ctx.getImageData function, and to get
| | 05:45 | the image data, I want all of the image data.
| | 05:47 | I want from the upper-left
corner down to the bottom right.
| | 05:50 | So this will get me all of the bytes
in the image. And then from the image data
| | 05:56 | that comes back, I want the data
property, because this is the array of bytes, and
| | 06:00 | I'm going to store that in a
local variable named pixels.
| | 06:04 | So now, I'm going to loop
over every row in the image.
| | 06:08 | So I'm starting off at row 0. While the
current row is less than the maximum row, I'm
| | 06:13 | going to have a five-row-high strip.
| | 06:16 | So I have this local counter named i,
which is going to count to our five rows.
| | 06:21 | Now remember, to get access to each
one of the rows' bytes, which is what this
| | 06:25 | variable right here is going to keep
track of, I need to take the current row,
| | 06:30 | add the local row counter.
| | 06:32 | So we're going to start off at 0 and
then go 0, 1, 2, 3, 4, 5 then go to the
| | 06:37 | next row, and so on.
| | 06:38 | So, to get to the current RowBytes, I
have the current row times the canvas
| | 06:42 | width, times four, because
there's four bytes in every pixel.
| | 06:47 | So this will move me to the beginning of
each row in the image, in the byte array.
| | 06:53 | Once I've done that, I then need to loop
across all the bytes in that particular row.
| | 06:58 | So we start off at 0, and then we go to
the canvas width times four, so that's all
| | 07:03 | the bytes. And we're going to increment
j by four each time, because we need to skip
| | 07:07 | over each pixel's four bytes.
So to skip over a pixel,
| | 07:10 | let's just skip over four bytes.
| | 07:12 | So each time through this loop, we're
going to say that the pixel's content at
| | 07:17 | thisRowBytes plus my index is equal
to the number 255, because that's the
| | 07:24 | maximum value of any given byte,
minus whatever's currently in there.
| | 07:28 | We're going to that for the red, the green,
and the blue components of each one of the bytes.
| | 07:33 | We're not going to do anything with the
alpha channel, although we could choose
| | 07:36 | to, but we're not going to right now.
| | 07:38 | So we're basically going to
invert all of the pixel values.
| | 07:42 | Then after we've done that, we
increment the current row by 15, so we skip over
| | 07:47 | to the next 15 rows, and we
let this remove complete.
| | 07:50 | So by the time this loop completes,
every 15th row will have a four-row-high strip
| | 07:57 | of inverted pixels. And when that's done,
we simply call putImageData to put the
| | 08:02 | image data back into the canvas. So let's save.
| | 08:06 | Let's refresh. You can see that what happened
here is you've got five rows where the pixels are
| | 08:12 | all being inverted from their original colors.
| | 08:16 | So here is the source image,
| | 08:17 | here's the canvas and our loop has gone
through and inverted every 15th row of
| | 08:24 | a five-row-high pixel strip.
| | 08:26 | We could stop there,
but let's go for the extra point.
| | 08:29 | Let's try using the optional dirty
rectangle, and remember this only affects the
| | 08:35 | bytes that are inside this rectangle.
| | 08:38 | So I'm just going to say 50, 50,
and let's make the rectangle 400 pixels wide.
| | 08:46 | Let's make it 200 pixels high.
| | 08:49 | So we'll save, and we will refresh.
| | 08:52 | See that now only the pixels inside of
that rectangle are the ones that got affected.
| | 08:57 | So in this example, we've seen how to
get access to the raw image data of a
| | 09:01 | canvas, manipulate the pixels, put
them back in, and optionally only affect a
| | 09:06 | certain range of pixels by a rectangle.
| | Collapse this transcript |
|
|
8. Building Practical ExamplesBuilding an image slideshow control| 00:00 | So we have reached the point now
where we can use what we've learned on the
| | 00:05 | HTML5 canvas to start building some
real live useful stuff and one of the first
| | 00:09 | things that we are going
to build is a slideshow.
| | 00:11 | So let me show you what the
slideshow looks like when it's finished.
| | 00:16 | So this is a fairly typical slideshow.
| | 00:20 | You can see the images are rotating.
| | 00:21 | There are four of them.
| | 00:23 | So when we reach the last one, after a
few seconds it goes back to the first one.
| | 00:27 | These images are all being drawn on
a canvas, and there is a few-seconds
| | 00:31 | delay between each one.
| | 00:33 | So let's see how to go and build this.
| | 00:36 | So I'll close this, and we will open
up the start version in my editor.
| | 00:43 | So this is SlideShow_start.
| | 00:45 | Let's go over to the snippets.
| | 00:46 | You can see this is way the snippets are.
| | 00:48 | I am under the Slideshow section.
| | 00:50 | So let's get started building the slideshow.
| | 00:53 | So I have got an empty document
here with a placeholder for the script.
| | 00:57 | So I am going to copy these
first few lines and paste them in.
| | 01:04 | So this is just some
initialization and setup code.
| | 01:08 | So let's just take a quick look at it.
| | 01:10 | I have an array here that has paths to all the
images that I am going to show in the slideshow.
| | 01:17 | I have a couple variables that refer to
the slideshow canvas and its context, and
| | 01:23 | I am creating a new image element using
the DOM, and I have a little indexer here
| | 01:27 | that keeps track of what the current image is.
| | 01:31 | So that's just the setup stuff.
| | 01:33 | Then we have a function,
and we will copy this over.
| | 01:40 | So now we are setting a function to
run when the window loads. And the first
| | 01:45 | thing we do is get the reference to
the canvas. We've done this before throughout the
| | 01:50 | title, and here we have the
reference to the canvas's context.
| | 01:56 | The first thing we do is set the width
and height of the newly created image
| | 02:01 | element up here to be 600 x 400,
which is the size of the images.
| | 02:07 | Then we have a function call to
switchImage, which we will write in second, and
| | 02:11 | then we have an interval which we are
going to use to switch the image every
| | 02:16 | 3,000 milliseconds, or three seconds.
| | 02:20 | So let's go ahead and copy that over.
| | 02:22 | So now we have the switchImage function.
| | 02:33 | So the switch image function simply
sets the source of the image object to
| | 02:40 | whatever the current image indexer is
looking at in the array of image paths.
| | 02:46 | So it's going to cycle
throughout. Here is the path.
| | 02:48 | It's going to start at 0 and then go to
1 and then go to 2 so on and so forth.
| | 02:52 | So the switchImage is responsible for
doing the heavy lifting of the example.
| | 02:57 | It displays the current image and
looks at the image in the array that's
| | 03:04 | currently being indexed by
the currentImage counter.
| | 03:06 | So up here we have the
image paths 0, 1, 2, and so on.
| | 03:11 | So the first thing it does is sets the
source attribute on the image object to
| | 03:15 | whatever path is being looked
at by the currentImage counter.
| | 03:19 | When that image loads we have a
function that runs, and it checks to see if the
| | 03:23 | current image is greater than the length
of the image path's array, because if it
| | 03:28 | is, we need to be reset it back
to 0 so it starts at the beginning again.
| | 03:31 | Then we simply call the drawImage
function on the canvas context to draw the
| | 03:36 | image at the location on the canvas,
starting at the upper-left corner and with
| | 03:41 | the given width and height.
| | 03:42 | And then, because of this interval,
the switchImage function is going to be
| | 03:46 | called each time the interval timer
goes off, which we've set to three seconds.
| | 03:51 | So, every three seconds the image counter
gets incremented, we look at the next
| | 03:55 | image, and we set the canvas context
to draw whatever the current image is.
| | 03:59 | So let's save, and let's go back to the browser.
| | 04:03 | If everything goes right then, yup,
you can see every three seconds that image is
| | 04:07 | going to change.
| | 04:09 | This is the last one here.
| | 04:10 | So, after three seconds it should go
back to the first one, and it does.
| | 04:13 | That's a pretty simple example of
using an interval timer and the canvas's
| | 04:18 | drawImage function to create a slideshow.
| | Collapse this transcript |
| Using smooth transitions in a slideshow| 00:00 | In this example, we are going to see
how to use smooth transitions to improve
| | 00:05 | upon the previous example where we
built an image slideshow control.
| | 00:10 | So what I am going to do is open up
the SlideShowSmooth_finished example and
| | 00:15 | show you what I mean.
| | 00:16 | In the other example, the transitions
between the images were pretty abrupt, but
| | 00:20 | you can see that what we are doing
here is gradually fading in each image to
| | 00:23 | create a nice smooth transition.
| | 00:25 | So let's see how to do that.
| | 00:27 | So I am going to open up my
SlideShowSmooth_start example.
| | 00:32 | This is our starting point.
And let's go back to the snippets.
| | 00:36 | So the setup code is the first
few lines we are going to copy over.
| | 00:41 | So let's paste that in.
| | 00:43 | So I have an array of all the image
paths and then variables that refer to the
| | 00:48 | canvas and the canvas context.
| | 00:51 | Then I create an image that's going to
be responsible for loading each one of
| | 00:54 | the images from the
local folder or from the web.
| | 00:57 | I have an indexer here that keeps
track of which image we are looking at, and
| | 01:01 | then finally, a variable that's going to be
the timer that smoothly reveals each image.
| | 01:07 | So it is called the revealTimer.
| | 01:08 | So let's go ahead and copy over
the initialization logic, and that's
| | 01:12 | this function here.
| | 01:14 | So let's paste that in.
| | 01:15 | So when the window loads--and
that's this function right here.
| | 01:19 | So when the window loads up, we are
going to get a reference to the canvas
| | 01:24 | and the canvas context.
| | 01:26 | Then, on the image, we are going to set
the height and width to be the height and
| | 01:29 | widths of the images that we
are going to be loading.
| | 01:32 | Then we call the switchImage function,
which shows the first image, and then we have
| | 01:37 | we have an animation that waits every three
seconds, which is 3,000 milliseconds, to
| | 01:41 | change to the next image.
| | 01:43 | So we will save that.
| | 01:46 | Now we need to copy over the two
functions that are the meat of how this works.
| | 01:51 | So let's copy over
switchImage, and I'll explain that one.
| | 01:56 | Now the switchImage function basically
looks at the current image index, gets
| | 02:01 | its path from the images array,
and then sets the source attribute of the image
| | 02:06 | object that we created up here using the
DOM, right there, to be pointing at the
| | 02:12 | source for whatever the current image index is.
| | 02:16 | Then we have a little check right here
| | 02:17 | to see if that current image counter,
which we're incrementing each time, if it's
| | 02:22 | bigger than the array that contains
the paths, we just need to set it back to 0.
| | 02:27 | Then we set the globalAlpha of the
canvas context to 0.1, or 10%--and we covered
| | 02:35 | this back in the globalAlpha movie.
| | 02:38 | Then we set the revealTimer to be an
interval of 100 milliseconds, or a 10th of a second.
| | 02:45 | So, every 10th of a second we are going
to call this revealImage function, which
| | 02:50 | we need to copy over.
| | 02:50 | Let's copy and we'll paste.
| | 02:59 | So let's take a look what the revealImage does.
| | 03:01 | So every three seconds, switchImage will be called.
| | 03:05 | Then we have another subInterval down here.
| | 03:07 | So revealImage saves the current
context of the canvas, and it then draws
| | 03:14 | the current image onto the canvas at the
upper-left corner using the width and height.
| | 03:18 | Then it increments the globalAlpha by 10%.
| | 03:22 | If the globalAlpha reaches
100%, then we stop the revealTimer.
| | 03:27 | So what's going to happen is every 10th of a
second this revealImage is going to be called.
| | 03:32 | So because we are incrementing the
globalAlpha by .1 each time, it's going to
| | 03:36 | be called 10 times.
| | 03:38 | So over a full second, we are going to
slowly fade the image onto the canvas on
| | 03:44 | top of what's already there.
| | 03:46 | After we do that, we will restore the
context, and then the function ends.
| | 03:49 | So we got two timers going on.
| | 03:51 | We've got one that's three seconds long and
we've got one that's 100 milliseconds
| | 03:56 | but executes 10 times, which is 1 second.
| | 03:59 | So let's save, and let's go back to
the browser and take a look of this.
| | 04:03 | Now I can see that over a course
of a second, the image fades in.
| | 04:07 | Then we wait a few
seconds and the next one fades in.
| | 04:10 | So the way that we are accomplishing
this is is by setting the globalAlpha to an
| | 04:13 | increment of 10% each time and then
just redrawing the image in place.
| | 04:17 | That gives the effect of
fading in over a smooth transition.
| | 04:21 | So now we have seen how to create
smooth transitions using the globalAlpha and
| | 04:26 | a JavaScript timer.
| | Collapse this transcript |
| Creating a basic animation| 00:00 | Part of the fun of working with HTML5
canvas is that you can learn how to do
| | 00:04 | things like animation.
| | 00:06 | So in this movie, we are going to see
how to use the canvas and some JavaScript
| | 00:11 | logic to make a basic animation sequence.
| | 00:15 | So let me show you what it looks like.
| | 00:17 | So here, I have a canvas that's light
blue with a rectangle, in this case a
| | 00:22 | square, that has a yellow interior and a
red stroke that's just moving from left
| | 00:28 | to right across the canvas, and when
it disappears from view over here, it
| | 00:33 | reappears over here.
| | 00:34 | So let's see how we built this.
| | 00:38 | So I am going to open up my start
version of the file, and what we are going to
| | 00:43 | do is we are going to take
a look at the snippets code.
| | 00:46 | So for the simple animation, let's go
ahead and copy over the first few lines
| | 00:52 | which initialize everything,
and we will paste that in there.
| | 00:56 | So I have got some initialization logic here.
| | 00:58 | I have got some variables for the
rectangle. The Y value is 200, the width is
| | 01:04 | 40, and then I've got an X position
which is equal to the initial value of the
| | 01:10 | rectWidth, but I negate that so it's -40.
| | 01:14 | And that so the rect appears completely
off the screen when it first gets drawn.
| | 01:20 | So let's go back to the snippets.
| | 01:22 | So let's copy the initialization function over.
| | 01:24 | We will copy this here.
| | 01:30 | So in the initialization function, we
get a reference to the canvas and then the
| | 01:34 | context, and then we call
a function called blank.
| | 01:36 | Blank draws the background
which we will copy over in a moment.
| | 01:40 | Then we have the logic
which draws the rectangle.
| | 01:42 | So we have a fillStyle of yellow,
and then we fill the rect with the yellow
| | 01:47 | content right here.
| | 01:49 | Let's go ahead and copy that over.
| | 01:50 | So I am going to copy over the blank function.
| | 01:55 | So you can see that the blank
function simply fills the canvas.
| | 02:03 | I have got a nice light blue color
right here, and it fills the rectangle which
| | 02:08 | is from the upper left to the
width and height of the canvas.
| | 02:12 | And notice, by the way, that I am
using the built-in canvas properties, like
| | 02:15 | width and height, rather than hard-coding the
values which are down here in the document.
| | 02:19 | That way if I ever want to change the
height of the canvas or make any other
| | 02:23 | changes, I can just change it in one
place and then my code automatically
| | 02:26 | picks up the difference;
| | 02:27 | I don't have to worry about
changing numbers in more than one spot.
| | 02:30 | So that draws the blank canvas background,
and then we've got drawing the rectangle.
| | 02:36 | Let's go back and copy some more code over.
| | 02:38 | This is the function
where the animation happens.
| | 02:43 | So let's go ahead and copy that.
| | 02:51 | So the animation function, you can see up here,
| | 02:54 | we set an interval every 30
milliseconds, which is about 30-ish or so frames per
| | 03:01 | second, to call the function
labeled anim, which is down here.
| | 03:07 | So every 30 milliseconds this
function will be called, and we check to see if
| | 03:13 | the X position of the rectangle is less
than the width of the canvas, and if it
| | 03:19 | is, we then draw the blank background,
| | 03:22 | we move the rectangle by five
pixels, and then fill it again.
| | 03:27 | So we fill it with yellow, we stroke it
with red and a lineWidth of 3, and then
| | 03:32 | we fill and stroke the rectangle.
| | 03:34 | Now if the rectangle has moved beyond
the canvas width, if the X and Y position
| | 03:40 | is greater than the width--in
this case, it is just the X position--
| | 03:43 | we then reset it back to being a
negative value of the rectWidth, which will
| | 03:48 | place the rectangle, again, back off the screen.
| | 03:51 | And the reason we do negative width
is because we want the X position to be
| | 03:55 | far enough to the left that none of the
rectangle peeks through on the left side of the canvas.
| | 04:02 | So to recap, we've got some initialization logic.
| | 04:06 | The first thing we do in the
initialization function is draw the blank
| | 04:09 | background, set up the initial
rectangle, and then start the animation.
| | 04:14 | The blank function just fills in the
background, and then every time through the
| | 04:19 | loop, we draw the background, draw the
rectangle. And each time we were drawing
| | 04:23 | the rectangle, we are
moving in over by five pixels.
| | 04:25 | So the effect that the user sees,
because this is happening so quickly, is the
| | 04:29 | blank background gets drawn,
which paints over the rect.
| | 04:32 | We move the rect by five pixels
and then we fill it again.
| | 04:35 | Now the example of animation that I am
showing here is called single buffering,
| | 04:38 | and the reason it is called that is
because all the animation is taking place
| | 04:42 | directly on the canvas that's in the page.
| | 04:44 | There's no buffer where we are drawing
everything and copying it onto the canvas.
| | 04:49 | So let's run this in the browser, save,
and we'll go to start. And you can see that
| | 04:56 | what's happening is the
rectangle is moving across the screen.
| | 05:00 | So it's happening too fast for you to
see it, but the blank background is being
| | 05:04 | drawn each time. The rectangle is moved
and then painted in its new location.
| | 05:08 | Now this looks pretty smooth because
there's only one moving object, but if this
| | 05:13 | animation contained a lot of moving
objects, we might start seeing things like
| | 05:17 | flicker, because all of the objects are
being erased, the background is being
| | 05:21 | drawn each time, and then everything
is being drawn on the canvas right here
| | 05:25 | directly in the page where the user can see it.
| | 05:28 | So what we see in this movie is an
example of creating simple animation with
| | 05:31 | what's called single buffering.
But later on in this chapter, we will see an
| | 05:35 | example of double buffering, which makes
it easier to draw multiple objects on a
| | 05:38 | canvas, and makes the animation
appear much smoother to the user.
| | Collapse this transcript |
| Creating animation with double buffering| 00:00 | In this movie, we're going to see how
to create a smooth animation using a
| | 00:04 | technique known as double buffering.
| | 00:06 | Double buffering is called that
because all the drawing takes place on an
| | 00:10 | offscreen canvas, or buffer, before
it is copied to the onscreen canvas.
| | 00:16 | The reason you do this is because if
you have a lot of objects that are being
| | 00:19 | animated, if you're just doing all the
animation directly on the screen, the
| | 00:23 | user might see things like flicker
or other unwanted artifacts that don't
| | 00:28 | happen when you draw everything offscreen first
and then copy the finished frame onto the canvas.
| | 00:34 | So let's take a look at the
example that we're going to build.
| | 00:36 | I'm going to bring up my finished
example, and you can see that what we have
| | 00:41 | here is a nice nighttime sky with
snowflakes of various sizes falling at various
| | 00:47 | speeds and randomly drifting
to the left at various rates.
| | 00:51 | So this is the example
that we're going to build.
| | 00:54 | You can see that it's nice and smooth.
| | 00:56 | There's no stuttering or anything like that.
| | 00:58 | So this example is using
double-buffering animation, so all the snowflakes are
| | 01:02 | being animated on a canvas that you
can't see off the screen, and then each
| | 01:06 | frame, as it's completed,
is copied onto the canvas.
| | 01:10 | So let's go ahead and build that.
| | 01:13 | I'm going to open up my start point
here in the editor and in the snippets and
| | 01:18 | at my Double Buffer Animation,
so let's copy things over.
| | 01:23 | So this is just some initialization code.
| | 01:25 | So here's the canvas and context
that's in the page, and that's this canvas
| | 01:30 | right here. But we also have
variables for the buffercanvas,
| | 01:34 | and this is a canvas that to
we're going to create offscreen.
| | 01:36 | We have an array to hold all the
snowflakes, we have a timer that is used to
| | 01:41 | animate each flake, and then we have a
variable that keeps track of the maximum
| | 01:45 | number of flakes we're going to
have on the screen. So let's save.
| | 01:49 | Let's copy over the initialization
function. So we copy that and we paste it.
| | 02:01 | So the initialization function will
get called when the document loads,
| | 02:04 | and that's right here.
| | 02:06 | So when the document loads, we're going
to get a reference to the canvas in the
| | 02:10 | context of the canvas that's in the page.
| | 02:14 | And we're going to use that
information to create a new buffer canvas.
| | 02:18 | So you can see we're using the
document's DOM right here to create a new canvas
| | 02:22 | element, and then retrieve its context.
| | 02:24 | Now this canvas is not in the page;
| | 02:26 | it's floating in space somewhere,
but we can still use it to draw on.
| | 02:29 | So once we've created the buffercanvas,
we set its width and height to the same
| | 02:33 | width and height of the
canvas that's already in the page.
| | 02:36 | Once we've initialized that, we set an
interval timer that adds snowflakes to
| | 02:42 | the scene over time.
| | 02:44 | So every 200 milliseconds, or pretty
much every fifth of a second, we'll be
| | 02:49 | adding a new snowflake.
| | 02:50 | Then we have a Draw function, which
draws the initial setting, and then we have
| | 02:55 | an animate timer which gets called
every 30 milliseconds, or about every
| | 03:00 | thirty-ish frames per
second or so. So let's save.
| | 03:05 | Let's copy over the animation function,
and the animation function is right here, paste.
| | 03:16 | So the animation function follows a
fairly standard pattern that you'll see
| | 03:19 | throughout various animation techniques.
| | 03:23 | Every time the animation function
gets called which is about 30 times per
| | 03:26 | second. The first thing it does is
call Update function, then it calls Draw.
| | 03:30 | Now Update is responsible for moving
all of the animated objects on the screen.
| | 03:36 | So it's going to move each one of
the snowflakes according to its speed
| | 03:42 | and drift and so on.
| | 03:43 | Once all the objects have been updated
to their new locations, we then call the
| | 03:47 | Draw function which updates the
scene and copies the contents of the
| | 03:51 | buffercanvas onto the onscreen canvas.
| | 03:55 | So now that we have that in place,
let's save, and let's copy over
| | 03:59 | the supporting logic.
| | 04:03 | So we have these two
functions, addFlake and blank.
| | 04:07 | Let's copy that, and we'll put those in
here. And let's copy over the Update and
| | 04:18 | Draw functions as well, and we'll
go through those and see what they do.
| | 04:24 | So I'm going to put those guys down here.
| | 04:30 | So as I mentioned earlier, we have
Update and Draw, and now we copied over
| | 04:34 | some supporting logic.
| | 04:35 | The last thing we need to copy over is
the logic that creates all the snowflakes.
| | 04:40 | So let's copy that over, and you can
see that right here in addFlake, we have a
| | 04:45 | call to a new Flake object.
| | 04:48 | So I'm going to copy that because that's up
here at the top, and we'll to paste that in.
| | 05:01 | So here's how this works.
| | 05:03 | So remember, we have a timer here that
adds snowflakes to the screen gradually
| | 05:09 | over time, and that's this function.
| | 05:12 | So we have an array; recall that
we have an array of snowflakes.
| | 05:16 | So each time this function gets called,
we're going to create a new snowflake
| | 05:20 | and put it in the array of snowflakes.
| | 05:22 | And then once the length of the
snowflake array has reached the maximum
| | 05:27 | number of flakes we want, we then
clear the snowflake timer so that no
| | 05:32 | further flakes get added.
| | 05:34 | So let's go back up and look at the
initialization logic for each snowflake.
| | 05:38 | So each snowflake on the screen is going
to have some properties associated with it.
| | 05:43 | So each snowflake has an x and y position,
and that's these two lines right here.
| | 05:48 | So the snowflake is going to start
out above the top of the canvas, so we
| | 05:52 | initialize that to be -10 pixels so
it appears off the canvas initially.
| | 05:57 | Then we want to distribute each
snowflake randomly along the X axis of the
| | 06:02 | canvas so that it has a different
starting position when it falls down.
| | 06:05 | So we're going to use the built-in
JavaScript's Math library to create a random
| | 06:11 | number, and the random function
gives us a random number between 0 and 1.
| | 06:16 | So we're going to multiply
that by the width of the canvas.
| | 06:19 | That will give us a random number that
goes from zero up to the far right of
| | 06:25 | the canvas, and then we'll just simply
use the rounding function to round that
| | 06:28 | to an n-digit number.
| | 06:30 | So now we've initialized the x and
y position of each snowflake, but we
| | 06:34 | don't want each snowflake to just fall
straight down--and that's kind of not very realistic.
| | 06:37 | We want each snowflake to
kind of drift a little bit.
| | 06:40 | So we have a drift property, and again,
we just have a little random number
| | 06:44 | between 0 and 1, and we're going to add
that to the x position each time to give
| | 06:48 | it a little bit of a drift.
| | 06:49 | Then we have the speed at
which each snowflake falls.
| | 06:54 | So again, to be realistic, we want
each snowflake to fall at a slightly
| | 06:58 | different speed, so we have a
random number between 0 and 1, times 5.
| | 07:03 | That will give us a random number
between 0 and 5. But we don't want zero
| | 07:07 | because we don't want any snowflakes
just sitting there out in space, not
| | 07:11 | falling in defined gravity.
| | 07:12 | So we add the number one to ensure that
every snowflake at least has some speed,
| | 07:19 | so this will now give us a
random number between one and six.
| | 07:23 | Then we have to make the width
and height of each snowflake.
| | 07:26 | So we're going to give
the width of the snowflake--
| | 07:28 | again, we want it to be realistic,
and snowflakes are varying sizes--
| | 07:32 | so we'll have a random number between 0
and 1, times 3, so that'll give us a width
| | 07:36 | between 0 and 3. But we can't have
snowflakes of zero width, and we want to make
| | 07:41 | sure that each snowflake is at least
visible, so we'll add the number 2 to that.
| | 07:45 | So now we have snowflakes of random
width at least 2 and at most 5.
| | 07:50 | And to make them square, we'll just set
the height to be whatever the width is.
| | 07:55 | So now that we've created each
snowflake, let's go back down and see what the
| | 07:58 | Update function does.
| | 08:00 | So remember, each time through the
animate loop, we're going to update, then
| | 08:03 | we're going to draw.
| | 08:04 | So in the Update logic, for all of the
snowflakes in the snowflake array, we
| | 08:09 | need to update their position
based upon their properties.
| | 08:13 | So we check to see if this snowflake,
if the y value is currently less than the
| | 08:18 | height of the canvas;
| | 08:19 | in other words, it still hasn't
reached the bottom of the canvas yet.
| | 08:22 | And if that's true, then we
update the snowflake's position.
| | 08:26 | So we update its vertical position by
adding the speed to whatever the y value
| | 08:31 | is that will cause the snowflake
to fall down a little bit more.
| | 08:35 | If doing that has now caused the
snowflake to fall off the bottom of the canvas--
| | 08:39 | in other words, the y value is
now greater than the canvas height--
| | 08:42 | we reset the y value to be -5.
| | 08:44 | That will reset it to be back
up above the top of the canvas.
| | 08:47 | So now we've updated the y position.
| | 08:49 | Now we have to update the x position.
| | 08:50 | Now remember, the x position gets
updated because we don't want the snowflake
| | 08:53 | to fall straight down;
| | 08:54 | we want it to kind of
drift a little bit randomly.
| | 08:57 | So each time through this animate loop,
we're going to add the snowflake's drift
| | 09:01 | amount to whatever its x position is.
| | 09:04 | Then just like for the y position logic,
we have to see if the x position is
| | 09:09 | now greater than the canvas width, because
it's drifted off the right side of the screen.
| | 09:13 | If that's the case, we simply reset
the x position of the snowflake to zero.
| | 09:17 | So this is going to happen for
all of the snowflakes in the array.
| | 09:20 | So now when this function completes,
all the snowflakes have been moved to
| | 09:24 | their new position.
| | 09:26 | So that means it's time
for the Draw function to run.
| | 09:28 | So after Update, the Draw function is
now responsible for drawing everything
| | 09:33 | in its new location.
| | 09:34 | So we have a save and a restore for the
context--and these aren't mandatory, but
| | 09:38 | it's a good practice to put them in.
| | 09:40 | I just put them there in case any
drawing comes before or after this particular
| | 09:43 | function, if I have a complex
animation that I'm working on.
| | 09:46 | The first thing we do is call the
blank function, and the blank function--
| | 09:50 | let's just scroll back up--all
this does is draw our night sky.
| | 09:53 | So we draw the background first with a
nice deep purplish color, and we fill
| | 09:59 | the rectangle on the buffercanvas, starting
at the upper left down to the lower right.
| | 10:04 | And again, you can see that all the
drawing is taking place on the offscreen
| | 10:09 | buffercanvas, not on the onscreen one.
| | 10:11 | So we just draw the background,
and then we draw all the snowflakes.
| | 10:19 | So once again, we have a loop that goes
across the entire snowflake array, and
| | 10:23 | for each one of the snowflakes, we
set the fillStyle of the canvas on the
| | 10:27 | buffercanvas to be white.
| | 10:29 | And then again, on the buffercanvas, we just
fill each rectangle represented by each snowflake.
| | 10:35 | So we have the x and y position and the
width and the height of each snowflake.
| | 10:40 | So we do that for all 200 flakes.
| | 10:43 | Then when we've drawn everything
to the buffercanvas, we copy the
| | 10:46 | entire rendered image,
| | 10:48 | this frame, from the buffercanvas
onto the canvas that's on the screen.
| | 10:53 | So we do that using the drawImage
function that's on the onscreen canvas to
| | 10:59 | copy the source, which is the buffercanvas.
| | 11:01 | And again, we copy from the upper-left
corner, all the way to the lower right.
| | 11:06 | So let's go ahead and
save, and let's try it out.
| | 11:09 | You can see now that we've got
snowflakes beginning to fill the sky, and we've
| | 11:12 | got a little drift going on, right?
| | 11:14 | Some of them are drifting, some of them
are falling at different a different speeds.
| | 11:18 | So now let's get little bit fancy.
| | 11:19 | Now let's add a clipping region,
and remember, we learned about clipping regions earlier.
| | 11:23 | So let's go back to the code.
| | 11:25 | So what we're going to do now is scroll down
here, and we're going to create a clipping region.
| | 11:32 | I'm going to copy this and I'm
going to paste it back in here.
| | 11:37 | So remember that clipping paths define
an area outside of which drawing does not
| | 11:43 | take place, and inside of
which drawing shows through.
| | 11:47 | So we're going to create a clipping
region by calling the beginPath function,
| | 11:51 | again, on the buffercanvas--all the
drawing takes place in the buffercanvas.
| | 11:55 | So we fill the entire buffercanvas
with a black rectangle, starting at the
| | 11:58 | upper left and going to the lower right.
Then we draw an arc, and the arc is
| | 12:04 | going to be drawn at the middle of
the buffercanvas, so we divide the width
| | 12:07 | by 2, the height by 2.
| | 12:08 | That gets at the center.
| | 12:09 | We're going to give the arc a radius
of 40% of whatever the canvas height is.
| | 12:16 | So it's going to reach 40% in all
directions. And since the radius is half the
| | 12:21 | diameter, this will give us a
circle of 80% of the canvas's height.
| | 12:26 | And then finally we call clip which
tells the canvas, only draw in the visible
| | 12:31 | area which is represented by that circle.
| | 12:33 | So let's save and let's see
what this does. Let's refresh.
| | 12:37 | Now we have a circle.
| | 12:39 | It's kind of like looking
through a telescope, right?
| | 12:41 | So now the snowflakes are only
visible within the circular area.
| | 12:46 | They're still being drawn out here.
| | 12:47 | You just can't see it because the clipping
region is precluding that from happening.
| | 12:51 | But the effect that we've created is
looking at a snowfall through say a telescope.
| | 12:57 | That's our finished example.
| | 12:58 | So in this movie, we've seen how to
create smooth animation using a technique
| | 13:02 | known as double buffering.
| | 13:04 | And for good measure, we added a
clipping region to clip the animation to a
| | 13:09 | visible area, providing a
nice nighttime snowfall effect.
| | Collapse this transcript |
| Incorporating Canvas into a real page| 00:00 | In this example, we're going to see how to
incorporate a canvas into a real web page.
| | 00:06 | And to do that, we are going to use
the Explore California example site that
| | 00:10 | comes with your exercise files.
| | 00:12 | So, here I've got the
ExploreCalifornia exercise files ready to go.
| | 00:16 | Let me first show you the
page that we are going to build.
| | 00:19 | So, if I bring up the index page, this
is the Explore California web site that
| | 00:23 | we've been working with. And I am going
to click on the TOURS section, and you can
| | 00:28 | see down here there is a list of tours.
| | 00:31 | What we are going to do is we are going
to build a canvas-based tour finder, and
| | 00:36 | here is what we are going to do.
Let's go to the TOUR FINDER page.
| | 00:39 | So, right now, you can see this
example is empty, but let me show you the
| | 00:43 | finished version so you can see
what it is going to look like.
| | 00:46 | Okay, it's going to look like this.
| | 00:49 | So, we will have a canvas which
displays a graph of some attributes of a given
| | 00:56 | tour, and it will show us things like
the duration, elevation, environment, and
| | 01:00 | overall difficulty of a given tour.
| | 01:03 | So you see, as we choose different tours,
the graph is changing to show us what
| | 01:08 | the overall difficulty is.
| | 01:09 | In this case, if it's easy, it
turns green and if it happens to be a
| | 01:13 | moderate tour, it turns yellow.
| | 01:15 | And in the case of really difficult tours,
you can see that the difficulty bar turns red.
| | 01:21 | And you notice how as I am choosing
each one of these tours, the graph is
| | 01:25 | changing right here in the page.
| | 01:27 | So, to do this without using canvas,
you would have a couple of choices.
| | 01:30 | You would either have to use some
other dynamic media solution, such as a
| | 01:34 | plug-in like either Silverlight or
Flash, or you would have to build each one
| | 01:40 | of these as a separate graphic image
and then swap out the image whenever a
| | 01:44 | new tour was chosen.
| | 01:46 | However, each time you added a new
tour or if you changed some of the data
| | 01:50 | associated with the particular tour,
you would then have to either make a new
| | 01:53 | image or go back and change the
existing one, which is kind of labor
| | 01:56 | intensive and is not really
well suited to data intensive examples. Because
| | 02:01 | again, let's suppose somebody goes and does
some work on this particular tour and makes it easier.
| | 02:06 | In the case of using the canvas, all
you have to do is change one little data
| | 02:09 | point and then the canvas graph
is going to update automatically.
| | 02:12 | To do this with an image or some other
complex dynamic media solution, there
| | 02:16 | would be a lot more work involved.
| | 02:18 | So, this is what we are going
to build, so let's go build it.
| | 02:21 | So, we are going to close this.
| | 02:22 | Let's go to the code.
| | 02:25 | So, here are the snippets for the
Explore California example here in chapter 08.
| | 02:30 | And I am going to go open up the
starting point file, and here we are
| | 02:34 | in ExploreCalifornia.
| | 02:36 | So, open up the tourcompare page, and
we're going to go ahead and scroll on down,
| | 02:43 | and I'll show you where
we are going to put this.
| | 02:45 | So, we are going to put this right
down here where it says tourDescriptions.
| | 02:51 | So, let's go back to our snippets and
paste in the content we are going to need
| | 02:56 | to let the user choose a
tour, and that's down here.
| | 03:02 | So, to do that, we are going to need
this snippet of code, and I will paste it in
| | 03:06 | and explain what it does. And we
are going to put that right there.
| | 03:11 | So, what I have done is I've pasted in
some HTML code that has a select list in
| | 03:15 | it, which is called tourSelector.
| | 03:18 | And you can see that there's a series
of options that allow me to choose the
| | 03:21 | different tours. And then below that, I
have my canvas, and you can see that my
| | 03:26 | canvas has an id on it, and it's got a
width and a height. And I put a little one-
| | 03:30 | pixel solid border around it
so we can see it in the page.
| | 03:33 | So just doing that, let me just save and let's
go back to the browser and see how that looks.
| | 03:37 | So, let's just go ahead and
bring the tourcompare page up.
| | 03:41 | And you can see that what I have done
so far is here is the canvas and here
| | 03:44 | is that select list.
| | 03:46 | So, we are already pretty well on our
way. All you do now is draw the canvas
| | 03:50 | and then respond to changes in this menu such
that when the menu changes, we redraw the canvas.
| | 03:56 | So, let's go back and do that.
| | 03:57 | Here we are back in the code.
| | 03:58 | So, let's scroll up to the script
portion, because that's where the rest of this
| | 04:03 | is going to take place, and
go back over to the snippets.
| | 04:07 | So, let's begin by copying
the first few lines of code.
| | 04:15 | And I will just copy this and explain it.
And I'll put the closing script tag on there.
| | 04:25 | So, what I have here is an array of
tourdata, and inside that array, there is a
| | 04:30 | series of objects, and there are
five of them for the five tours.
| | 04:34 | There is a few properties
associated with each object.
| | 04:36 | There is the tour name.
| | 04:37 | There is the tour duration.
| | 04:40 | And I just chose these numbers
arbitrarily on some scale, so these are just
| | 04:44 | going to happen to work out to the size
of the bars on the chart, but if you had
| | 04:49 | some other prior existing data, you
could put whatever you wanted in a chart
| | 04:53 | like this and then just do whatever
conversion you need to do to make the chart
| | 04:56 | draw the right size bars.
| | 04:58 | In this case, just to make the
example simple, I have just got a 1:1
| | 05:01 | relationship between these numbers.
| | 05:03 | So, for example, a duration of 200
means two days and so on and so forth.
| | 05:07 | So, we have got duration.
| | 05:09 | You got values for elevation, value for
how extreme the environment is, and then
| | 05:14 | an overall difficulty rating.
| | 05:16 | So, there is five objects, and then
I have got a couple of variables here
| | 05:20 | that are going to hold a reference to the
tour canvas and the context for that canvas.
| | 05:25 | So, let's go back to the snippets.
| | 05:27 | Now, let's copy over the drawChart function.
| | 05:33 | This is the function that's going to get
called every time the select list index changes.
| | 05:38 | So, this will take care of drawing
the chart backgrounds, drawing the labels,
| | 05:41 | and drawing the data.
| | 05:42 | So, let's copy over those.
| | 05:44 | Let's copy over drawBackground first.
| | 05:47 | So, I will copy this
function over and we'll paste it.
| | 05:54 | And for the time being, what we will do
is we'll fill in little empty stubs for
| | 05:59 | draw labels and draw tour data.
| | 06:01 | So, we'll say function drawLabels
(forWhichTour) and we will have a function
| | 06:13 | drawTourData again (forWhichTour).
| | 06:22 | So, now we have those functions stubbed out
and we can go ahead and take a look at the code.
| | 06:28 | Actually, before we do that,
let me do one more thing.
| | 06:31 | Let's copy over the initialization
code that sets up the chart when the page
| | 06:36 | first loads, and that's
this code right down here.
| | 06:44 | So, here I'm using the jQuery code to
create a function that runs when the page
| | 06:50 | loads, and for the moment,
| | 06:52 | let's go ahead and comment this one out.
| | 06:53 | What it's doing is it gets reference
to the canvas, then gets the canvas's
| | 06:58 | drawing context, and then it calls
drawChart with 0 to initialize the chart to
| | 07:03 | the first set of tour data.
| | 07:04 | So, let's go ahead and save, and let's
review this in the browser. Let's refresh.
| | 07:11 | And you can see that right now we've
got the canvas background drawing and the
| | 07:15 | drawing area, so let's go to
the code and see how that works.
| | 07:18 | So, up here in the
drawBackground, a couple of things happened.
| | 07:22 | First, I save off the canvas context.
| | 07:25 | Again, I just do that because it's a
nice practice in case any drawing came
| | 07:28 | before this function got called.
| | 07:30 | So, the first thing we do is
fill in the chart background.
| | 07:32 | So, we set the fillStyle to that
brownish color, and then we call fillRect
| | 07:36 | starting from the upper left and doing it
for the entire width and height of the canvas.
| | 07:39 | That's pretty simple.
| | 07:41 | Then we create the graph area.
| | 07:42 | So, we change the strokeStyle to a
somewhat darkish gray color, and then we
| | 07:46 | call strokeRect, and that's what gives
us the outline of the area where we are
| | 07:50 | going to draw the bars.
Then we need to draw the chart lines.
| | 07:53 | So, we change the strokeStyle to a
slightly lighter gray color, and then we have
| | 07:57 | a loop that starts at a certain point
on the canvas, at the x point, goes to a
| | 08:02 | certain x point, and increments every 20 pixels.
| | 08:05 | So, inside that loop, we begin a path,
and then we just draw each line and
| | 08:09 | stroke it, and that just creates that
little bars across the drawing area,
| | 08:13 | and then we are done.
| | 08:14 | We restore the canvas
context, and the function exits.
| | 08:17 | So, now let's fill in the drawLabels function.
| | 08:20 | The drawLabels function is
responsible for two things:
| | 08:25 | it draws the tour name and it draws the labels.
| | 08:28 | So, let's copy that code and paste it in.
| | 08:34 | So, again, we save and
restore the context each time.
| | 08:37 | Again, that's a nice little practice--
not mandatory in this case, but we
| | 08:40 | are doing it anyway.
| | 08:41 | So, now we draw the tour name, so we
set the font to be 24pt Arial, and we
| | 08:45 | set the fillStyle to be the blue text color,
and then we just call the fillText routine.
| | 08:51 | FillText takes the constant string tour
name plus the tour data's name property
| | 08:58 | for whatever the currently selected tour
is and draws that text at this location
| | 09:03 | on the canvas, so that's that part.
| | 09:07 | And for the labels, we change it to 20pt
Arial and the fillStyle for that color,
| | 09:12 | and then we draw the labels for duration,
elevation, environment, and difficulty.
| | 09:16 | Again, we just use the fillText
function at various points on the canvas.
| | 09:20 | Let's save and let's refresh.
| | 09:22 | So, we can see this being
built up slowly over time.
| | 09:25 | So, you can see that here's the labels that
we drew on the canvas using the text function.
| | 09:29 | Here's the tour name for the currently
selected tour. And it starts out to 0, so
| | 09:33 | that's the first data object.
| | 09:35 | Now, what we need to do is draw the bars
for the various data points and respond
| | 09:40 | to changes in this menu.
| | 09:42 | So, back in the code, let's go ahead
and uncomment this function right here.
| | 09:47 | So, what we're doing is we are using
jQuery to listen for the change event on
| | 09:53 | the select list. Remember, we
had the id of tourSelector.
| | 09:57 | So, we are listening to the change event,
and whenever the change event fires, we
| | 10:00 | are simply calling a function that
calls drawChart and we are getting the
| | 10:05 | selectedIndex of the select list.
| | 10:08 | So, this will go from 0 up to 4 because that's
how many options there are in the select list.
| | 10:14 | So, now that we've got
that working, we can save.
| | 10:18 | And before we go ahead and draw
the data, let's just go ahead and see
| | 10:21 | the effects of that.
| | 10:22 | So, we refresh and now you can see that
as I change the menu, it's changing the
| | 10:28 | currently selected tour,
so the title is changing.
| | 10:30 | All right, so now let's go back to the
code, and now let's fill in the part where
| | 10:35 | we actually draw the data and that's down here.
| | 10:39 | So, what we are going to do is copy
this, and we are going to paste it in to
| | 10:49 | the drawTourData part.
| | 10:51 | So, let's go ahead and refresh the
browser and see what the effects of this was.
| | 10:56 | So, now we are getting the data drawn
as well, and you can see that each time we
| | 11:00 | are changing the selection, the data changes.
| | 11:03 | So, let's go back to the
code and explain what happened.
| | 11:06 | As you may have guessed, drawing each one of
those bars on the chart is just a rectangle.
| | 11:11 | So to do that, recall that we set
the strokeStyle and the fillStyle for
| | 11:15 | the rectangle, and then it is just a matter
of drawing each bar for the four properties.
| | 11:21 | And remember, the forWhichTour index
gets passed in from the function for
| | 11:26 | drawing the chart, so we use that
as an index into the tourData array.
| | 11:31 | So, we get each object and we just get
the duration, elevation, environment, and
| | 11:35 | then the difficulty for that particular tour.
| | 11:38 | So, you can see that that's just a
simple matter of calling fillRect and
| | 11:41 | strokeRect for each one of those data points.
| | 11:45 | At a particular point on the canvas
starting here, they get this width.
| | 11:49 | The value of that data field in that
object just serves as the width, and each
| | 11:54 | one of those bars is 30 pixels high.
| | 11:56 | So, we fill each rectangle, and then
we stroke it with a grayish color to
| | 11:59 | give it an outline.
| | 12:01 | So, we do that for each one of the data points.
| | 12:03 | Now, notice for the other properties,
it's always yellow. But for difficulty, we
| | 12:09 | are actually going to draw different
colors based upon whether the tour is easy
| | 12:13 | or hard or moderate.
| | 12:16 | So, we've chosen a green color for easy
yellow, yellow for moderate, and red for hard.
| | 12:20 | So, that's just a simple matter of
changing the fill style based upon what the
| | 12:24 | difficulty rating is.
| | 12:25 | So, we check the difficulty rating, and
if it's less than or equal to 150, we
| | 12:29 | choose the green color.
| | 12:30 | If it's between 150 and 300, we choose
the yellow color. And if the difficulty is
| | 12:37 | more than 300, we choose the red color.
And then we just fill and stroke the
| | 12:41 | difficulty rect and draw it appropriately.
| | 12:44 | So, we save, refresh.
| | 12:47 | And you can see now that as we choose
each tour, we are getting a real-time
| | 12:53 | chart drawn in the page.
| | 12:55 | And let's just go ahead and
try this in another browser.
| | 12:57 | I am going to switch over to
Firefox. Okay, here we are in Firefox.
| | 13:02 | You can see, again, the same
appearance, same behavior, right.
| | 13:07 | So, we have built an
interactive tour finder using canvas.
| | 13:12 | So, let's just recap really quickly.
| | 13:14 | So, using the canvas, we built an
area here in the page and we hooked up a
| | 13:19 | select list whose change event we used
to get the selected index to choose which
| | 13:24 | tour data we are going to draw.
| | 13:26 | We used rectangles, text, we used some
paths in or to draw the canvas, and that's
| | 13:31 | a real live example of
incorporating campus into a real web page.
| | Collapse this transcript |
|
|
ConclusionGoodbye| 00:00 | All right! That brings us to the end of HTML5:
Graphics and Animation with Canvas.
| | 00:05 | I hope you enjoyed learning
about the canvas element as much as I
| | 00:07 | enjoyed teaching it.
| | 00:08 | The canvas element really
represents a huge leap forward in graphics
| | 00:12 | capabilities for the web and finally
enables web developers to build many of
| | 00:17 | the same advanced and sophisticated
effects that native application developers
| | 00:20 | have had for years.
| | 00:22 | In this course, we covered everything,
from drawing basic shapes to using complex
| | 00:26 | techniques like patterns, gradients,
transformations, and clipping paths.
| | 00:31 | We even saw how to create animation
using the canvas and how to incorporate the
| | 00:34 | canvas into a real-world web page.
| | 00:37 | But this is just the beginning.
| | 00:38 | You should take what you've learned
in this course and use your creativity and
| | 00:42 | imagination to build web pages that
benefit from the techniques we've learned here.
| | 00:46 | Happy coding!
| | Collapse this transcript |
|
|