You are previewing HTML5 Canvas.

HTML5 Canvas

Cover of HTML5 Canvas by Steve Fulton... Published by O'Reilly Media, Inc.
  1. HTML5 Canvas
    1. SPECIAL OFFER: Upgrade this ebook with O’Reilly
    2. A Note Regarding Supplemental Files
    3. Preface
      1. Running the Examples in the Book
      2. What You Need to Know
      3. How This Book Is Organized
      4. Conventions Used in This Book
      5. Using Code Examples
      6. We’d Like to Hear from You
      7. Safari® Books Online
      8. Acknowledgments
    4. 1. Introduction to HTML5 Canvas
      1. The Basic HTML Page
      2. Basic HTML We Will Use in This Book
      3. The Document Object Model (DOM) and Canvas
      4. JavaScript and Canvas
      5. HTML5 Canvas “Hello World!”
      6. Debugging with Console.log
      7. The 2D Context and the Current State
      8. The HTML5 Canvas Object
      9. Another Example: Guess The Letter
      10. What’s Next
    5. 2. Drawing on the Canvas
      1. The Basic File Setup for This Chapter
      2. The Basic Rectangle Shape
      3. The Canvas State
      4. Using Paths to Create Lines
      5. Advanced Path Methods
      6. Compositing on the Canvas
      7. Simple Canvas Transformations
      8. Filling Objects with Colors and Gradients
      9. Filling Shapes with Patterns
      10. Creating Shadows on Canvas Shapes
      11. What’s Next
    6. 3. The HTML5 Canvas Text API
      1. Displaying Basic Text
      2. Setting the Text Font
      3. Text and the Canvas Context
      4. Text with Gradients and Patterns
      5. Width, Height, Scale, and toDataURL() Revisited
      6. Final Version of Text Arranger
      7. What’s Next
    7. 4. Images on the Canvas
      1. The Basic File Setup for This Chapter
      2. Image Basics
      3. Simple Cell-Based Sprite Animation
      4. Advanced Cell-Based Animation
      5. Applying Rotation Transformations to an Image
      6. Creating a Grid of Tiles
      7. Zooming and Panning an Image
      8. Pixel Manipulation
      9. Copying from One Canvas to Another
      10. What’s Next
    8. 5. Math, Physics, and Animation
      1. Moving in a Straight Line
      2. Bouncing Off Walls
      3. Curve and Circular Movement
      4. Simple Gravity, Elasticity, and Friction
      5. Easing
      6. What’s Next?
    9. 6. Mixing HTML5 Video and Canvas
      1. HTML5 Video Support
      2. Converting Video Formats
      3. Basic HTML5 Video Implementation
      4. Preloading Video in JavaScript
      5. Video and the Canvas
      6. Video on the Canvas Examples
      7. Animation Revisited: Moving Videos
      8. What’s Next?
    10. 7. Working with Audio
      1. The Basic <audio> Tag
      2. Audio Formats
      3. Audio Tag Properties, Functions, and Events
      4. Playing a Sound with No Audio Tag
      5. Creating a Canvas Audio Player
      6. Case Study in Audio: Space Raiders Game
      7. What’s Next
    11. 8. Canvas Game Essentials
      1. Why Games in HTML5?
      2. Our Basic Game HTML5 File
      3. Our Game’s Design
      4. Game Graphics: Drawing with Paths
      5. Animating on the Canvas
      6. Applying Transformations to Game Graphics
      7. Game Graphic Transformations
      8. Game Object Physics and Animation
      9. A Basic Game Framework
      10. Putting It All Together
      11. The player Object
      12. Geo Blaster Game Algorithms
      13. The Geo Blaster Basic Full Source
      14. Rock Object Prototype
      15. What’s Next
    12. 9. Combining Bitmaps and Sound
      1. Geo Blaster Extended
      2. Creating a Dynamic Tile Sheet at Runtime
      3. A Simple Tile-Based Game
      4. What’s Next
    13. 10. Mobilizing Games with PhoneGap
      1. Going Mobile!
      2. Creating the iOS Application with PhoneGap
      3. Beyond the Canvas
      4. What’s Next
    14. 11. Further Explorations
      1. 3D with WebGL
      2. Multiplayer Applications with ElectroServer 5
      3. Conclusion
    15. Index
    16. About the Authors
    17. Colophon
    18. SPECIAL OFFER: Upgrade this ebook with O’Reilly
O'Reilly logo

Chapter 3. The HTML5 Canvas Text API

The HTML5 Canvas Text API allows developers to render text on an HTML page in ways that were either tricky or next to impossible before its invention.

We are providing an in-depth analysis of the HTML5 Canvas Text API because it is one of the most basic ways to interact with the canvas. However, that does not mean it was the first Canvas API feature developed. In fact, for many browsers, it was one of the last parts implemented.

There was a time in the recent past when HTML5 Canvas Text API support in browsers was spotty at best. Back then, using modernizr.js to test for text support would have been a good idea. However, at this historic moment, all modern browser versions (besides IE) support the HTML5 Canvas Text API in some way.

This chapter will create an application named “Text Arranger” to demonstrate the features and interdependencies of the HTML5 Canvas Text API. This application will display a single line of text in an almost infinite number of ways. This is also a useful tool to see whether support for text is common among web browsers. Later in this chapter you will see that some text features are incompatible when drawn on the canvas at the same time.

Displaying Basic Text

Displaying text on HTML5 Canvas is simple. In fact, we covered the very basics in Chapter 1. First, we will review these basics, and then we will show you how to make them work with the Text Arranger application.

Basic Text Display

The simplest way to define text to be displayed on the canvas is to set the context.font style using standard values for CSS font style attributes: font-style, font-weight, font-size, and font-face.

We will discuss each of these attributes in detail in the upcoming section Setting the Text Font. All you need to know now is that a font designation of some type is required. Here is a simple example of setting a 50-point serif font:

context.font = "50px serif";

You also need to set the color of the text. For filled text, you would use the context.fillStyle attribute and set it using a standard CSS color, or with a CanvasGradient or CanvasPattern object. We will discuss the latter two options later in the chapter.

Finally, you call the context.fillText() method, passing the text to be displayed and the x and y positions of the text on the canvas.

Below is an example of all three basic lines of code required to display filled text on HTML5 Canvas:

context.font = "50px serif"
context.fillStyle = "#FF0000";
context.fillText ("Hello World", 100, 80);

If you do not specify a font, the default 10px sans-serif will be used automatically.

Handling Basic Text in Text Arranger

For Text Arranger, we are going to allow the user to set the text displayed by the call to context.fillText(). To do this, we will create a variable named message where we will store the user-supplied text. We will later use that variable in our call to context.fillText(), inside the standard drawScreen() method that we introduced in Chapter 1 and will continue to use throughout this book:

var message = "your text";
...

function drawScreen() {
  ...
  context.fillStyle = "#FF0000";
  context.fillText  (message, 100, 80);
}

To change the text displayed on the canvas to the text entered by the user, we need to create an event handler for the text box keyup event. This means that whenever someone changes text in the box, the event handler function will be called.

To make this work, we are going to name our text box in our HTML <form> using an <input> form element. Notice that the id is set to the value textBox. Also notice that we have set the placeholder="" attribute. This attribute is new to HTML5, so it might not work in every browser. You can also substitute it with the value="" attribute, which will not affect the execution of this application:

<form>
  Text: <input id="textBox" placeholder="your text"/>
  <br>
</form>

Communicating Between HTML Forms and the Canvas

Back in our JavaScript code, we need to create an event handler for the keyup event of textBox. We do this by finding the form element using the document.getElementById() function of the DOM document object, and storing it in the formElement variable. Then we call the addEventListener() method of formElement, setting the event to keyup and the event handler to the function textBoxChanged, which we have yet to define:

var formElement = document.getElementById("textBox");
formElement.addEventListener('keyup', textBoxChanged, false);

The final piece of the puzzle is to define the textBoxChanged() event handler. This function works like the event handlers we created in Chapter 1. It is passed one parameter when it is called, an event object that we universally name e because it’s easy to remember.

The event object contains a property named target that holds a reference to the HTML form element that created the change event. In turn, the target contains a property named value that holds the newly changed value of the form element that caused the event to occur (i.e., textBox). We retrieve this value, and store it in the message variable we created in JavaScript. It is the very same message variable we use inside the drawScreen() method to paint the canvas. Now, all we have to do is call drawScreen(), and the new value of message will appear “automagically” on the canvas:

function textBoxChanged(e) {
      var target = e.target;
      message = target.value;
      drawScreen();
   }

We just spent a lot of time describing how we will handle changes in HTML form controls with event handlers in JavaScript, and then display the results on an HTML5 Canvas. We will repeat this type of code several more times while creating Text Arranger. However, we will refrain from explaining it in depth again, instead focusing on different ways to render and capture form data and use it with Canvas.

Using measureText

The HTML5 Canvas context object includes a useful method, measureText(). When supplied with a text string, it will return some properties about that text based on the current context settings (font face, size, etc.) in the form of a TextMetrics object. Right now the TextMetrics object has only a single property: width. The width property of a TextMetrics object gives you the exact width in pixels of the text when rendered on the canvas. This can be very useful when attempting to center text.

Centering text using width

For the Text Arranger application, we will use the TextMetrics object to center the text the user has entered in the textBox form control on the canvas. First, we retrieve an instance of TextMetrics by passing the message variable (which holds the text we are going to display) to the measureText() method of the 2D context, and storing it in a variable named metrics:

var metrics = context.measureText(message);

Then, from the width property of metrics, we get the width of the text in pixels and store it in a variable named textWidth:

var textWidth = metrics.width;

Next, we calculate the center of the screen by taking the width of the canvas and dividing it in half (theCanvas.width/2). From that, we subtract half the width of the text (textWidth/2). We do this because text on the canvas is vertically aligned to the left when it is displayed without any alignment designation (more on this a bit later). So, to center the text, we need to move it half its own width to the left, and place the center of the text in the absolute center of the canvas. We will update this in the next section when we allow the user to select the text’s vertical alignment:

var xPosition = (theCanvas.width/2) - (textWidth/2);

What about the height of the text?

So, what about finding the height of the text so you can break text that is longer than the width of the canvas into multiple lines, or center it on the screen? Well, this poses a problem. The TextMetrics object does not contain a height property. The text font size does not give the full picture either, as it does not take into account font glyphs that drop below the baseline of the font. While the font size will help you estimate how to center a font vertically on the screen, it does not offer much if you need to break text onto two or more lines. This is because the spacing would also need to be taken into account, which could be very tricky.

For our demonstration, instead of trying to use the font size to vertically center the text on the canvas, we will create the yPosition variable for the text by simply placing it at one-half the height of the canvas. The default baseline for a font is middle, so this works great for centering on the screen. We will talk more about baseline in the next section:

var yPosition = (theCanvas.height/2);

Note

In the chat example in Chapter 11, we will show you an example of breaking up text onto multiple lines.

fillText and strokeText

The context.fillText() function (as shown in Figure 3-1) will render solid colored text to the canvas. The color used is set in the context.fillColor property. The font used is set in the context.font property. The function call looks like this:

fillText([text],[x],[y],[maxWidth]);

where:

text

The text to render on the canvas.

x

The x position of the text on the canvas.

y

The y position of the text on the canvas.

maxWidth

The maximum width of the text as rendered on the canvas. At the time of this writing, support for this property was just being added to browsers.

fillText in action

Figure 3-1. fillText in action

The context.strokeText() function (as shown in Figure 3-2) is similar, but it specifies the outline of text strokes to the canvas. The color used to render the stroke is set in the context.strokeColor property; the font used is set in the context.font property. The function call looks like:

strokeText([text],[x],[y],[maxWidth])

where:

text

The text to render on the canvas.

x

The x position of the text on the canvas.

y

The y position of the text on the canvas.

maxWidth

The maximum width of the text as rendered on the canvas. At the time of this writing, this property does not appear to be implemented in any browsers.

strokeText setting outline properties

Figure 3-2. strokeText setting outline properties

The next iteration of Text Arranger adds the ability for the user to select fillText, strokeText, or both. Selecting both will give the fillText text a black border (the strokeText). In the HTML <form>, we will add a <select> box with the id fillOrStroke, which will allow the user to make the selections:

Fill Or Stroke:
<select id = "fillOrStroke">
  <option value = "fill">fill</option>
  <option value = "stroke">stroke</option>
   <option value = "both">both</option>
</select>

In the canvasApp() function, we will define a variable named fillOrStroke that we will use to hold the value selected by the user on the HTML <form>. The default value will be fill, which means Text Arranger will always show fillText first:

var fillOrStroke = "fill";

We will also create the event listener for a change in the fillOrStroke form element…

formElement = document.getElementById("fillOrStroke");
formElement.addEventListener('change', fillOrStrokeChanged, false);

…and create the function fillOrStrokeChanged() to handle the event:

function fillOrStrokeChanged(e) {
      var target = e.target;
      fillOrStroke = target.value;
      drawScreen();
   }

In the drawScreen() function, we test the fillOrStroke variable to see whether it contains the value fill. Since we have three states (fill, stroke, or both), we use a switch statement to handle the choices. If the choice is both, we set the strokeStyle to black (#000000) as the highlight for the colored fillText.

If we use the xPosition and yPosition calculated using the width and height of the canvas, the message variable that contains the default or user-input text, and the fillOrStroke variable to determine how to render the text, we can display the text as configured by the user in drawScreen():

var metrics = context.measureText(message);
var textWidth = metrics.width;
var xPosition = (theCanvas.width/2) - (textWidth/2);
var yPosition = (theCanvas.height/2);

switch(fillOrStroke) {
   case "fill":
      context.fillStyle = "#FF0000";
      context.fillText  (message,  xPosition,yPosition);
      break;
   case "stroke":
      context.strokeStyle = "#FF0000";
      context.strokeText  (message, xPosition,yPosition);
      break;
   case "both":
      context.fillStyle = "#FF0000";
      context.fillText  (message, xPosition,yPosition);
      context.strokeStyle = "#000000";
         context.strokeText (message, xPosition,yPosition);
         break;
      }

Example 3-1 shows the full code for Text Arranger. Test it out to see how the user controls in HTML affect the canvas. There are not many ways to change the text here, but you can see the difference between fillText and strokeText. In the next section, we will update this application to configure and render the text in multiple ways.

Example 3-1. Text Arranger 1.0

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CH3EX1: Text Arranger Version 1.0</title>
<script src="modernizr-1.6.min.js"></script>
<script type="text/javascript">

window.addEventListener("load", eventWindowLoaded, false);
function eventWindowLoaded() {

   canvasApp();
}

function canvasSupport () {
    return Modernizr.canvas;
}

function eventWindowLoaded() {

   canvasApp();
}

function canvasApp() {

   var message = "your text";
   var fillOrStroke ="fill";

   if (!canvasSupport()) {
          return;
        }

   var theCanvas = document.getElementById("canvasOne");
   var context = theCanvas.getContext("2d");

   var formElement = document.getElementById("textBox");
   formElement.addEventListener("keyup", textBoxChanged, false);

   formElement = document.getElementById("fillOrStroke");
   formElement.addEventListener("change", fillOrStrokeChanged, false);

   drawScreen();

   function drawScreen() {
      
      //Background
      context.fillStyle = "#ffffaa";
      context.fillRect(0, 0, theCanvas.width, theCanvas.height);
      
      //Box
      context.strokeStyle = "#000000";
      context.strokeRect(5,  5, theCanvas.width−10, theCanvas.height−10);

      //Text
      context.font = "50px serif"

      var metrics = context.measureText(message);
      var textWidth = metrics.width;
      var xPosition = (theCanvas.width/2) - (textWidth/2);
      var yPosition = (theCanvas.height/2);

      switch(fillOrStroke) {
         case "fill":
            context.fillStyle = "#FF0000";
                context.fillText (message, xPosition,yPosition);
            break;
         case "stroke":
            context.strokeStyle = "#FF0000";
            context.strokeText (message, xPosition,yPosition);
            break;
         case "both":
            context.fillStyle = "#FF0000";
                context.fillText (message, xPosition ,yPosition);
            context.strokeStyle = "#000000";
            context.strokeText (message, xPosition,yPosition);
            break;
      }

   }

   function textBoxChanged(e) {
      var target = e.target;
      message = target.value;
      drawScreen();
   }

   function fillOrStrokeChanged(e) {
      var target = e.target;
      fillOrStroke = target.value;
      drawScreen();
   }

}

</script>
</head>
<body>
<div style="position: absolute; top: 50px; left: 50px;">
<canvas id="canvasOne" width="500" height="300">
 Your browser does not support HTML5 Canvas.
</canvas>

<form>

  Text: <input id="textBox" placeholder="your text" />
  <br>

  Fill Or Stroke :
  <select id="fillOrStroke">
  <option value="fill">fill</option>
  <option value="stroke">stroke</option>
  <option value="both">both</option>
  </select>
  <br>

</form>

</div>
</body>
</html>

The best content for your career. Discover unlimited learning on demand for around $1/day.