Since I have not posted anything about the Canvas in a few weeks I wanted to show some of the experiments I’ve been working on. Everyone knows that animating text in Flash is very easy and has been around since the technology began. It seems to me, that if the Canvas is going be a “Flash killer”, then it must have as robust, if not more-so features than Flash. You can read the Canvas text API here: http://dev.w3.org/html5/2dcontext/#text and see for yourself, but from my view it does not appear to have as many features as Flash at all. Still, I wanted to try it out and see what was possible. Here then is my demo of a HTML5 Canvas text animation.
http://www.8bitrocket.com/wp-content/uploads/2010/07/textblog_movetext.html
Yes, it is true. The HTML 5 Canvas can be used to created some of the same gaudy crap that Flash has been doing for years. Not all of what Flash can do, but some of it. Enough to be dangerous anyway. It’s funny, the HTML guys have complained for years about “stupid Flash animations”, yet now they have their own tool to do exactly the same thing. Will they practice restraint?
Code Breakdown
Here are the interesting bits of the code. I’m not going to talk about the basics of the canvas, you can get that from here: HTML 5 Canvas For Flash Developers #1: What The #@*! Is The HTML 5 Canvas? or here Exploring The HTML 5 Canvas For Flash Developers #2: Tracking The Mouse To Draw On The Screen.
Animation Loop
It’s simple to put text on a Canvas, put animating it is another matter. The Canvas uses an immediate mode drawing paradigm which means he entire screen must be redrawn every time you want to move an object or objects. Unless you are a fan of blitting (we are!) most Flash developers are used to having the player keep track of their objects and redraw them on the screen on each frame. Because of this, they don’t need to custom code an animation loop. With the HTML 5 Canvas, you need to create your own loop to have things move on the screen. The code to do this is in the box below. Here are the details of this code:
- After the page loads (eventWindowLoaded() callback function) we use a setInterval function that should be very familiar to Flash developers (especially those versed in AS2). We set the interval to call appLoop() every 50 milliseconds.
- The appLoop() only does one thing: calls drawScreen(). This is where you will code all of your “immediate mode” screen manipulations. Remember, there is no display list, so you will be redrawing EVERYTHING on EVERY call to drawScreen().
- The clearScreen() function is called on every time we are going to redraw. It will perform two functions. It will draw the background, and it will reset and global transformations (i.e. alpha) so that they don’t effect the drawing of the background.
[cc lang=”javascript” width=”550″]function eventWindowLoaded() {
…
setInterval(“appLoop()”, 50);
…
}
function appLoop() {
drawScreen();
}
function drawScreen() {
clearScreen();
}
function clearScreen() {
context.clearRect(0, 0, 600,400);
context.fillStyle = ‘#000000’;
context.fillRect(0, 0, 600, 400);
}
[/cc]
Moving Text
Now we are going to move some text back and forth across the screen. The steps below describe the code we will create to do this:
- First, we create a variable named text1Dir that we will use to tell us which direction the text is moving. We want to make sure that we can reverse direction of the text when it reaches the side of the screen.
- Next we create a variable to hold the calculated x position of the text: text1Xpos;
- We use a variable named text1 to describe the text that will be displayed: text1 = “Hello Canvas!”;
- In drawScreen() we will start adding code that will redraw the text in text1 every time the function is called.
- We use the measureText() function of the 2D context to find the width of the text in text1. The function returns an instance of metrics that contain only one property(at this time), width.
- We use this width to determine if the text has reached the right side of the canvas( (if (text1Xpos > 600-text1Width))) or the left side of the canvas( if (text1Xpos < 10) ).
- If it has reached either side, we will switch directions using the text1Dir variable (“right” or “left“)
- If we have not reached either side, we will update the position of the text (text1Xpos) based on the direction in text1Dir: “right”: (text1Xpos += 10;) or “left”: (text1Xpos -= 10;)
- Finally, we apply the new text to the screen:
context.fillText ( text1 , text1Xpos, 180);
[cc lang=”javascript” width=”550″]function eventWindowLoaded() {
…
text1Dir =”right”;
text1 = “Hello Canvas!”;
…
}
function drawScreen() {
…
metrics = context.measureText(text1)
text1Width = metrics.width;
if (text1Dir == “right”) {
text1Xpos += 10;
if (text1Xpos > 600-text1Width) {
text1Dir = “left”;
}
} else {
text1Xpos -= 10;
if (text1Xpos < 10) {
text1Dir = “right”;
}
}
context.font = ’20px _sans’;
context.fillStyle = ‘#FF0000’;
context.textBaseline = ‘top’;
context.fillText ( text1 , text1Xpos, 180);
}
[/cc]
Text Size
We are going to use a similar set of code to that of the movement, for both sizing the text, and for creating the alpha fade on the text. The idea is that we keep track of the direction (for size it will be “up” or “down” instead of “right” and “left” for movement) and reverse accordingly when we reach a limit set in the code.
- We create a variable to hold the “direction” of the resize: text1SizeDir = “up”;
- We create a variable to hold the font size of the text: text1FontSize=20;
- In drawScreen() we use text1SizeDir to determine what the next font size for the text will be when we redraw it.
- We apply the font size to the text like this: context.font = text1FontSize + ‘px _sans’;, simply appending the font size to the font declaration for context.
[cc lang=”javascript” width=”550″]function eventWindowLoaded() {
…
text1SizeDir = “up”;
text1FontSize=20;
…
}
function drawScreen() {
…
if (text1SizeDir == “up”) {
text1FontSize += 2;
if (text1FontSize > 40) {
text1SizeDir = “down”;
}
} else {
text1FontSize -= 2;
if (text1FontSize < 20) {
text1SizeDir = “up”;
}
}
…
context.font = text1FontSize + ‘px _sans’;
…
}
[/cc]
Text Alpha Transparency For Fading
Uses an Alpha value for fading the text is very similar to text size and movement except for one major fact: alpha is “global transition” and thus must be used with special care as it will apply to everything on the screen when it is redrawn. For this reason, we will need to add a line of code to the clearScreen() function that resets the alpha before we draw the background. like AS3, alpha is set between the numbers 1 and 0 (AS2 uses a percentage).
- The text1AlphaDir variable is similar to text1SizeDir as it uses the value “up” and “down”, however we will start it with the value “down” which signifies that we will start by fading the text.
- In drawScreen() we will set context.globalAlpha just before we display the text on the screen. Everything draw after context.globalAlpha will be drawn with the value set for the alpha. It must be reset for anything that does not need the alpha value.
- We will increment and decrement the alpha value by .1, or 10% each time we redraw the screen.
- We reset the context.globalAlpha in clearScreen() to 1 so that the background will be drawn with no alpha fade.
[cc lang=”javascript” width=”550″]function eventWindowLoaded() {
…
text1AlphaDir = “down”;
…
}
function drawScreen() {
…
if (text1AlphaDir == ‘up’) {
text1Alpha +=.1;
if (text1Alpha > .9) {
text1AlphaDir = “down”;
}
} else {
text1Alpha -=.1;
if (text1Alpha < .1) {
text1AlphaDir = “up”;
}
}
context.globalAlpha = text1Alpha;
…
}
function clearScreen() {
…
context.globalAlpha = 1;
….
}
[/cc]
Text Shadow
Finally, we get to the text shadow. Shadows are fairly easy to create. However, since they are set as part of the global context, you need to be careful how you use them. There are 4 attributes that need to be set to create a shadow:
- context.shadowColor : The color of the shadow. #XXXXXX hex format is valid.
- context.shadowOffsetX : The number of pixels to set the shadow on the x axis of the image.
- context.shadowOffsetY : The number of pixels to set the shadow on the y axis of the image.
- context.shadowBlur : The number of pixels to spread a blurring effect across both axis
[cc lang=”javascript” width=”550″] function drawScreen() {
…
context.shadowColor = ‘#DDDDDD’;
context.shadowOffsetX = ‘2’;
context.shadowOffsetY = ‘2’;
context.shadowBlur = ‘2’;
…
}
[/cc]
Full Code Listing
Here is the full code listing for this little gem:
[cc lang=”javascript” width=”550″]
// 40) {
text1SizeDir = “down”;
}
} else {
text1FontSize -= 2;
if (text1FontSize .9) {
text1AlphaDir = “down”;
}
} else {
text1Alpha -=.1;
if (text1Alpha 600-text1Width) {
text1Dir = “left”;
}
} else {
text1Xpos -= 10;
if (text1Xpos
Your browser does not support the HTML 5 Canvas.
[/cc]
There are more things that you can do with text, but most of them are manipulations of the global context. I’ll report back when I have mastered that aspect of the canvas to make something worth showing. However, the point of this tutorial is to show that while some of the FX you can create with the HTML 5 Canvas are similar to those in Flash, creating them takes a lot more low level code than seems reasonable for a Flash designer. Obviously, tools will be created to build some of these things automatically (you can bet Adobe is on it right now), but those tools will still end-up writing out code much like this…all of it clearly visible in the HTML page.