Exploring The HTML 5 Canvas For Flash Developers #2: Tracking The Mouse To Draw On The Screen

After a week where confusion about the future of the Flash platform has been piled on to developers by moves outside their control, we present the second in our series of HTML 5 Canvas for Flash Developers.  We call these tutorials, but really they are more like explorations.  We are learning this thing at the same time you are learning it.  hopefully these will be beneficial in the long run.

Drawing On The HTML 5 Canvas

One of the most basic things that can be accomplished with an HTML Canvas is drawing with the mouse. In this tutorial we will quickly show you the code for achieving this in HTML 5 with a Canvas element. We are not saying this is the best or most efficient way to do it, just one way to tackle the problem.

Creating A Simple Flash-like”Trace” Window In HTML

The first thing that will drive Flash developers crazy when working in browser JavaScript is the lack of good, out of the box, debugging tools for the web browser. You can install things like Firebug, or use an “alert” box, but we have a found a much simpler, easier way to create a “Flash-like” trace() in JavaScript, on the same page as the Canvas. It is very basic and involves a and JavaScript function named “trace()”. but the usage is fairly simple. insert trace() calls in your code, just like you would in Flash, and they will show-up in the on the HTML page. It’s a simple, brute-force way to test your running JavaScript. The code is below. You will see this demonstrated on our code page i nthe next section.

[cc lang=”javascript” width=”550″]
var trace;
function trace(text) {
document.trace.tracetext.value +=’n’ + text;
}

 

trace started[/cc]

 

[/cc]

 

Note: you may need to update the style position of the trace() box depending on the size of your canvas, or where you would like it to appear on the screen. You can also use something like JsTrace to solve this problem, but we had fun making our own anyway.

Preloading The Page

Yep, Flash developers, just like in good old ActionScript, you will need to know when the HTML page has finished loading before you can start working with your . This goes for any kind of JavaScript. As a Flash developer you will need start thinking in Flash” terms for HTML, even if you are not used to doing that. Pre-loading is just the first one.

You can test to see if the browser window has loaded by listening for the “load” event like this:

[cc lang=”javascript” width=”550″]window.addEventListener(‘load’, eventWindowLoaded, false); [/cc]

Notice below that you will never see the “started” trace in out trace window, just the “loaded” one. This is because the trace() function does not exist before the page is loaded.

[cc lang=”javascript” width=”550″]<!
main();
var trace;
function main() {
window.addEventListener('load', eventWindowLoaded, false);
trace('started');
}
function eventWindowLoaded() {
trace('loaded');

}

[/cc]

Test the code.

 

Loading The Canvas Element

Next we need to get a reference to the element we created on the HTML page. This is roughly the equivalent of getting a reference to the document class in AS3. The name of the element we will create in the HTML is “canvasOne”. After we that, we create a 600×400 rectangle on the canvas and fill it with a dark color. This will act as the background of the bitmap canvas.

[cc lang=”javascript” width=”550″]
function eventWindowLoaded() {

trace(‘loaded’);
var elem = document.getElementById(‘canvasOne’);

if (!elem || !elem.getContext) {
return;
}
context = elem.getContext(‘2d’);
if (!context) {
return;
}
context.fillStyle = ‘#DDDDDD’;
context.fillRect(0, 0, 600, 400);

Your browser does not support the HTML 5 Canvas.

[/cc]

Tracking Mouse movement

To continue, we will now track the movement of the mouse over the canvas. To do this, we will add some Event Listeners that are very similar the ones you would us in Flash. Since elem is a reference to the canvas, we will add listeners for “mousemove”, “mousedown”, mouseup” and then create callback functions for each (eventMouseUp, eventMouseDown, eventMouseMove)

Now, you will notice something that will give you hives as a Flash Developer: browser specific code. To make sure we are tracking the proper location on the canvas in Firefox and Opera, we must test some values and adjust accordingly. This code appears in the eventMouseMove() function below. To be honest, this type of checking might go away as browser support for HTML 5 continues to improve, but for now it appears to be a necessary check, so we have left it in the code. Since I’m no expert in cross browser JavaScript, I won’t even try to explain why this is required. However, you can get more information here http://dev.opera.com/articles/view/html5-canvas-painting/. notice, this site has a very similar painting example (this tutorial was based, in part, on the examples shown there) that you should explore after you read this as it adds even more functionality than we do here.

All the code does below is track the mouse and use our new “Trace” window to tell us where the mouse is when it moves. We will use this information in the next example to draw on the canvas.

 

[cc lang=”javascript” width=”550″]function eventWindowLoaded() {

trace(‘loaded’);
var elem = document.getElementById(‘canvasOne’);
elem.addEventListener(“mousemove”,eventMouseMove, false);
elem.addEventListener(“mousedown”,eventMouseDown, false);
elem.addEventListener(“mouseup”,eventMouseUp, false);

if (!elem || !elem.getContext) {
return;
}
context = elem.getContext(‘2d’);
if (!context) {
return;
}
context.fillStyle = ‘#DDDDDD’;
context.fillRect(0, 0, 600, 400);

}

function eventMouseMove(event) {

if ( event.layerX || event.layerX == 0) { // Firefox
mouseX = event.layerX;
mouseY = event.layerY;
} else if (event.offsetX || event.offsetX == 0) { // Opera
mouseX = event.offsetX;
mouseY = event.offsetY;
}

trace(‘mouse move’ + mouseX +”,” + mouseY);

}

function eventMouseDown() {
trace(“Mouse Down”);

}

function eventMouseUp(event) {
trace(“Mouse Up”);

}
[/cc]

Test the code.

 

Drawing

In this final example, we will add the drawing functions. The first thing we will do is add a new boolean variable named isDrawing and set it to false. We will use this vazribale to test to see if the mouse button is pressed and drawing at any given moment.

Next, we will add some code to the the eventMouseDown() and eventMouseUp() functions. These function will now set isDrawing to true (down)or false (up) for that our onMouseMove() function will know if it should draw anything on the canvas or not:

[cc lang=”javascript” width=”550″]function eventMouseDown()
{
isDrawing = true;
}
function eventMouseUp(event)
{
isDrawing = false;
}
[/cc]

Now we get to the heart if the drawing function. in eventMouseMove()we will use this isDrawing boolean to figure out what we are suppose to do.

If isDrawing is false, we always get set to draw if we need do it the next time eventMouseMove() is called. We do this by calling context.beginPath() and then by setting the current context to draw at the mouse location with context.moveTo(). however we DON’T DRAW yet. We just get ready to draw. If isDrawing is true, then we set the color to red with context.strokeStyle = ‘#FF0000’; set the line with context.lineTo(mouseX, mouseY); and then draw it with context.stroke();

[cc lang=”javascript” width=”550″] if (!isDrawing) {
context.beginPath();
context.moveTo(mouseX, mouseY);

} else {

context.strokeStyle = ‘#FF0000’;
context.lineTo(mouseX, mouseY);
context.stroke();

}

[/cc]

One other interesting thing to note about this code is the

that contains the canvas element in the HTML code. I was having trouble with the offsets of the mouse position relative to position of the canvas on the screen (even with the magic broswer-specifc JavaScript above). If it was lower on the screen screen using some hard white-space (i.e.

etc), the drawing on the canvas would be offset by that much. However, I was able to fix this by using absolute positioning with the

on the page:

[cc lang=”javascript” width=”550″]

Your browser does not support the HTML 5 Canvas.

[/cc]

Even though this has worked in every browser I have tried, I can’t tell you positively that it will work everywhere. I hope this is a permanent fix for calculating the mouse x,y position offsets. I’m sure we will learn a lot more about this as these tutorials continue.

Anyway, test this code below. We are all learning this stuff together, so any ideas, comments, etc. would be greatly appreciated. If you find some browser oddities or inconsistencies (or simply some code improvements) don’t hesitate to make us aware of them.

[cc lang=”javascript” width=”550″]

HTML 5 Canvas Project #1: Hello World
<!
main();
var mouseX;
var mouseY;
var context;
var trace;
var isDrawing = false;
function main() {
window.addEventListener('load', eventWindowLoaded, false);
trace('started');
}

function eventWindowLoaded() {
trace('loaded');
var elem = document.getElementById('canvasOne');
if (!elem || !elem.getContext) {
return;
}

context = elem.getContext('2d');
if (!context) {
return;
}
elem.addEventListener("mousemove",eventMouseMove, false);
elem.addEventListener("mousedown",eventMouseDown, false);
elem.addEventListener("mouseup",eventMouseUp, false);

context.fillStyle = '#DDDDDD';
context.fillRect(0, 0, 600, 400);
}

function eventMouseMove(event) {

if ( event.layerX || event.layerX == 0) { // Firefox
mouseX = event.layerX ;
mouseY = event.layerY;
} else if (event.offsetX || event.offsetX == 0) { // Opera
mouseX = event.offsetX;
mouseY = event.offsetY;
}

if (!isDrawing) {
context.beginPath();
context.moveTo(mouseX, mouseY);

} else {

context.strokeStyle = '#FF0000';
context.lineTo(mouseX, mouseY);
context.stroke();

}
trace('mouse move' + mouseX +"," + mouseY);

}

function eventMouseDown() {
trace("Mouse Down");
isDrawing = true;

}

function eventMouseUp(event) {
trace("Mouse Up");
isDrawing = false;

}

Your browser does not support the HTML 5 Canvas.

function trace(text) {
document.trace.tracetext.value +=’n’ + text;
}

<div style="position: absolute; top: 600px; left: 50px;"

trace started

[/cc]

 

Test the code.

Flash Developer Digestion

Did you notice something about this code? We never created any objects or MovieClips or Sprites or any other high level object to define the screen, the background, or anything we drew. Drawing the way we did in the is example is akin to using an old “plotter” printer. We kept adjusting the “print head” the moveTo() functions, and then comitted them to “paper” with the lineTo(); and stroke(); This is the method we will use as we continue these tutorials. We will think of the Canvas one a piece of paper that we either continuously draw to (like this example) or needs to be completed erased and redrawn every time time we need to change something (like when you move a sprite in a game).

So you can now see, the HTML 5 Canvas is really just a low-level display area for you to draw on to. In the next lesson we will start adding and tracking bitmap images.

 

 

 

Leave a Reply