HTML5, 20 Lessons to Successful Web Development (2015)
PART II HTML5 and the Canvas
LESSON 9 Accessing the Canvas
To view the accompanying video for this lesson, please visit mhprofessional.com/nixonhtml5/.
This is a simple page that displays a link to the Yahoo! website and has a form underneath that submits a username to a PHP script with the filename form.php. Beneath that an image is included. In terms of this web page’s DOM, it looks something like Figure 9-1, in which the entire content is contained within <html> and </html> tags.
FIGURE 9-1 The DOM of the preceding HTML example
Looking at the <head> section in Figure 9-1, you can see that there are two elements. The first is the document’s title of Example, contained within <title> and </title> tags, while the second is the meta tag, which tells search engine crawlers that the document may be crawled, its contents indexed, and any links can be followed. This is done by passing the value robots to the name attribute, and index, follow to the content attribute. Meta tags are self-closing (empty) so there is no </meta> tag. The section is then closed with a </head> tag.
To the right of the figure is the body of the document, which is contained within <body> and </body> tags. There are three elements in this section, a link to yahoo.com in <a> and </a> tags, an embedded image that uses a self-closing <img> tag, and a form contained within <form> and</form> tags.
The form assigns the value login to the id attribute, post to the method attribute, and the program name form.php to the action attribute. This is the program that is to process the form when it is submitted. The opening <form> tag is then closed, and inside the form there are two self-closing <input> tags. The first passes the value name to the name attribute, the value text to the type attribute, and the value jane to the name attribute. This prepopulates the input field with the word jane, but it can be altered by the user.
After this a second <input> tag creates a submit button by passing the value submit to its type attribute. Finally the form is closed with a </form> tag.
When opened in a browser, the document looks something like Figure 9-2.
FIGURE 9-2 The result of displaying the example web page
Similarly the form method type of post is easily changed to get, like this:
Using the getElementById() Function
For example, if the <img> tag is given an id (such as image1) with which it can be identified, it’s possible to replace the image loaded by it with another, like the following, in which the male-shaped dad.jpg image is replaced with mom.jpg to match the default name in the form field ofjane:
So let’s look at another example by restoring the name and image mismatch by altering the default name value. If we were to use the initial example in this section, we would have to access the element via document.forms.login, and so on, but by giving the form field an id (for example of name) and using getElementById(), we can avoid all that and go straight to the element to change it, like this (in which I have shown only the changed <input> tag and not the remainder of the HTML, which remains unchanged):
See how much easier it is than having to remember whether an element is part of a form, an image, or something else? All you have to do is know the name of an element and getElementById() will do the job of finding it for you. Figure 9-3 shows how the web page now displays after these changes. The title is different, the default input value is ′mike′, and the image shown is mom.jpg (yes, the gender is all confused again).
The Simpler O() Function
Doing this saves 22 characters of typing each time the replacement O() function is used instead of the longer one. One reason for the tremendous shortening is that the preceding document keyword has also been incorporated into the O() function, saving on typing that in too.
However, there’s one further step I like to take that makes the function even more useful and that’s to allow the passing to it of either element IDs (which is what it does so far), or an object that is the result of having called the O() function.
Let me explain it like this. Instead of directly manipulating the value of the form input with the id of name directly, let’s first create what is called an object from this element, like this:
newobject = O(′name′)
Now that I have this object, I can access it several times without ever having to call the O() function again, like this (in which the value is changed on separate occasions):
Now, whenever I wish to refer to the element in question, I can simply use the object that I created. But now, what if I want to change the style property of an object? Because the S() function I created for this (shown after this paragraph) calls the O() function, and that only supports idnames, then the only way to do this is to go back to using a call such as this (to make the input exactly 150 pixels wide):
S(′name′).width = ′150px′
But I have been using the object newobject, and for the sake of consistency, I would prefer to pass that to the S() function. To enable this, all that’s necessary is to allow the O() function to be passed either an object or an id, so the argument passed in obj is analyzed by the code and if it happens to already be of the type object, then the object is simply returned, because it is already an object.
But if it is not of that type, then it must be an id name, in which case it is looked up and returned as an object with a call to getElementById().
The Partner S() Function
FIGURE 9-4 The mom.jpg image has been reduced in size.
The // characters create a comment to the end of the line, which I have used in the preceding example to comment each of the final two lines within the script (that the second version of syntax is shorter than the first).
What I’ve done here is simply make the S() function place a call to the O() function but with an added .style suffix, and now I can use O() for accessing elements by name, and S() for accessing the style attributes of elements by name.
Alternatively, if you would like to create an object on the first call to the O() function, and then reference that instead, the preceding code might look like this:
This code can be quicker as the object is only looked up once, and is therefore a more efficient way to code when an element may be accessed more than once. By the way, the reason myimage does not have quotation marks around it is because it is an object, not an id value that is a string.
I use the functions O() and S() extensively throughout this book, so I recommend you get comfortable with them by downloading the examples from the companion website and then playing with them until you feel you have mastered their use.
The <canvas> Tag
With that little (but necessary) preamble over, now we can get down to directly manipulating an HTML5 canvas. As you may recall from Lesson 8, the following code creates a canvas and places a square in its center (and results in Figure 9-5):
FIGURE 9-5 Drawing a black square on a gray canvas
The other thing to remember about the <canvas> tag is that anything between it and the closing </canvas> tag is ignored by all HTML5-compatible browsers, and so is displayed only by browsers that do not recognize it. Therefore this is where you can place text and/or HTML to inform users about what they are missing and perhaps how to upgrade their browser.
Let’s look closely at the code from the previous example, as follows:
Ignoring the opening and closing tags, and the O() and S() functions, the object canvas is created by passing the id of the canvas (canvas1) to the O() function.
Armed with this object, the following line passes it to the S() function and then sets its background property to a light gray (#ddd) color. This is where the power of extending the O() function to also support objects comes in (because the S() function calls the O() function). By virtue of this extension it has been a simple matter to pass the object created from the canvas straight to the S() function, allowing for far simpler and more compact coding.
Then the final line uses this context to create a filled rectangle at an offset of 150 pixels horizontally in from the top-left corner, and 100 pixels vertically down from the same corner. The rectangle is given a width and height of 100 pixels, resulting in a filled, black square.
From now on, I will be assuming that you have placed the two functions O() and S() within <script> and </script> tags somewhere in your document, and will not be showing the code for these functions in any more examples. So please ensure that you have included them before testing any examples, or they will not work.
Converting a Canvas to an Image
Because of the way the canvas is created, it is not possible for users to right-click and save a copy to the desktop, for example. Likewise, you cannot directly use a canvas as an image. But there is a way you can convert a canvas to what is known as a data URL. This displays as an image and can then be copied and/or saved.
Consider the following code in which a canvas is created and then followed by an image, which does not have any src attribute:
What this code does (remember, it assumes you already have the O() and S() functions listed somewhere) is identical to the previous example, but there is a new line of code at the end that accesses the image using the O() function and then attaches a value to its src attribute, which is gained by calling the toDataURL() function on the canvas object.
The toDataURL() function extracts the image data from the canvas referred to by the canvas object and returns a string of text in which the canvas has been encoded as a displayable image, which is interpreted by the browser and reconstructed into an image.
When the code is loaded into a browser, it displays as Figure 9-6. Notice how the background color of the canvas (which has been applied only to the canvas element and not the contents of the canvas) is ignored by the toDataURL() function, so that when the image data is extracted, you see only the central black square.
FIGURE 9-6 Displaying a canvas and a copy saved into an image
The imagetype Argument
When an image is created from a canvas, you can choose the type of image to use between a jpeg and png image using the imagetype argument, as in the following two examples, which are identical in result since the default image type is png.
Or, for a jpeg image, you can use code such as the following three examples, which create a very low-quality, medium-quality, and a very high-quality image by passing an additional argument containing a value between 0 (low quality) and 1 (high quality):
Remember that the canvas object is used to call the toDataURL() method, not the context object. This is because the latter is for applying changes to the canvas using the context rendering assigned, while the former refers to the canvas object itself.
Uses for this feature could be online image manipulation programs that run in the browser (as opposed to on a web server somewhere far away from the browser), and which returns a transformed or newly created image ready for the user to save to their hard disk and use. This means that it is possible to use the HTML5 canvas to create a graphics program, like Photoshop, that runs within a browser and requires no interaction with a web server. Therefore it could also be turned into a web app or even a standalone app for a mobile device like a tablet or phone.
Now that you understand the basic elements of the HTML5 canvas, and have the tools and information required to use it, in the following lesson I explain in depth how to use each aspect of the features available for writing to a canvas, including drawing lines, rectangles, and circles; changing colors; using pattern and gradient fills; writing text; changing font face; using lines, paths, and curves; applying images to a canvas; adding shadows; direct pixel manipulation; compositing and transparency; transformations and translations, and more. By the time you complete the next lesson, you will be an expert at using the HTML canvas.
Test how much you have learned in this lesson with these questions. If you don’t know an answer, go back and reread the relevant section until your knowledge is complete. You can find the answers in the appendix.
1. What is the DOM?
6. What is the purpose of the O() function in these examples?
7. What is the purpose of the S() function in these examples?
8. What kind of object is needed to be created from a canvas object in order for drawing functions to operate correctly?