Drawing Text on Canvas

Keith Peters
InstructorKeith Peters
Share this video with your friends

Social Share Links

Send Tweet

With the HTML canvas you can easily draw text as well as graphics. Let's take a look at basic text manipulation on the canvas.

[00:00] In addition to lines, curves, and fills, it's often useful to draw a text on a canvas. The 2D rendering context has a number of properties and methods relating to this. To better see where the canvas is, I've drawn a light gray rectangle here, then, set the fill back to black.

[00:15] The key method here is fillText. You supply this with a string of text and the (x, y) position where you want to draw that text. For example, we can say, "context.fillText("Hello world", 100, 100)."

[00:32] Of course, like any other method that takes a string, this string can be in the form of a quoted string, a variable containing a string, or any expression that evaluates to a string.

[00:41] Before we go any further into this, let's look at how to change the font that's used to draw the text, as using a larger font will make it easier to see the changes as we look at other features.

[00:51] The font is set by assigning a string to context.font. The format of this string is essentially the same format you'd use when setting the font property in a CSS selector.

[01:01] The default is a black, 10-pixel, sans-serif font. In practice, you'll minimally need to enter a font size followed by a font family. Here, I'll say, "50 px Arial." You can see that the font has changed to reflect that. You can also precede that with a font style or weight, such as italic or bold.

[01:23] Now that we have some text that we can see better, let's look at the positioning of it. If I set the x position to zero, that moves the text, as expected, to the far left of the canvas.

[01:34] If I set the y position to zero, the text disappears. This is because the registration point for where the text is drawn corresponds to the lower left corner of the text.

[01:45] For (00the text is actually extending up off the top of the canvas, where it won't be visible. If we push the y down a bit, we'll see it appear bit-by-bit. There's another way to change this by using the textBaseline property, which we'll get to shortly.

[02:00] The color of the text is controlled by the context fillStyle, just like any other fill drawn on the canvas. Here, I'll change it to red. You could, of course, create a gradient fill here as well.

[02:13] Since we have fillText, you might be wondering if there's a way to stroke some text. Sure there is. Just call strokeText. Like any other shapes, you can fill and stroke the same text to get an outline effect.

[02:26] When we position the text to an (x, y) point, I said that the text is registered with a lower-left corner on that point. We can change that.

[02:34] First, horizontally, with the textAlign property. This is a property of the 2D rendering context and defaults to the string "left." I'll change the x of the position point to canvas.width.

[02:47] That will put it way over on the right-hand side of the canvas. Of course, now, you can't see the text at all, because it extends off the right side of the canvas, but we can set context textAlign to the string "right." Now, the text is magically aligned to the right side of the canvas.

[03:04] Then, I could set the point to canvas.width divided by two, making the right-hand side of the text align to the center of the canvas. I can change textAlign to the string "center." We have perfectly centered text.

[03:20] In addition to left and right, you can use start and end as textAlign values. These will do the same thing for Western text, but it will correctly adjust for text that runs right to left instead of left to right. There is a direction property that controls the text direction, but we're not going to delve into that in this video.

[03:39] If we're adjusting the vertical alignment, we can use the textBaseline property of the 2D rendering context. This is a bit more complex than the textAlign property as there are various features of text that you might want to use to set the alignment.

[03:52] The possible values here are the strings "top," "hanging," "middle," "alphabetic," "ideographic," and "bottom." The default is alphabetic, which aligns to the bottom of most characters, but lower-case letters like "j" or "y" will descend below the baseline.

[04:10] Here, I'm changing the text to a longer string and reducing the font size. Then, I'll draw a horizontal line at a "y" of 50 to represent where we're positioning the text. You can see how the descenders of some lower-case characters extend below that line.

[04:28] Setting textBaseline to bottom aligns all the texts so that the bottom of those descenders just touches that line. Of course, setting textBaseline to top will align the text so it extends down from the given y point.

[04:41] Now, the text will be aligned with its top on that line. I'll leave it to you to investigate the other possible values for textAlign.

[04:47] The last method I want to discuss is measureText. When you draw some text to the canvas, it's sometimes important to know the size of what you've just drawn. Unfortunately, in its current state, measureText probably won't do everything you would hope, but it's still very useful.

[05:02] The way measureText works is that you pass it a string of text. It will give you back an object that represents the size of that text on the canvas if it were to be drawn with the current font settings.

[05:13] The object is called a "TextMetrics object." There are plans for it to include some very useful properties, such as a full bounding box of the text as it would be rendered.

[05:22] Unfortunately, for now, the only guaranteed property you'll get is width. Some beta versions of Chrome and Firefox allow you to get the new advanced properties, but we'll ignore those for now, because they're not in common use. Let's see this in action.

[05:38] I'll change the text here back to "Hello world" and set it to a position of (150, 150). I'll get a TextMetrics object by calling measureText, passing in the same text I just rendered. Then, I can get a value for the width of the text right from that TextMetrics object.

[05:53] Remember that it's important to measure the text after you've set the font for the text you want to measure. A different font or a different size font will give you different measurements. I can now stroke a rectangle at (150, 150) using the width I just measured and a height of -50.

[06:11] The -50 is because the font size is 50 and the textBaseline is alphabetical, meaning that a rectangle will have to extend upward to surround the text.

[06:22] There we have a rectangle, which pretty much surrounds the text. While the width is right on, you might need to tweak the height a bit, perhaps by changing the baseline.

[06:31] Again, in the future, there should be some more useful properties on the TextMetrics that will make it all a bit easier. That's about all there is to text. You might want to look into the direction property, as well, if you wind up doing any work with right to left languages.