If you want to use the canvas element as the basis for a game, you will have to figure out what you're goin to do about events. A game will have user interface elements on the screen like sliders or buttons, and sometimes mouse or key events will need to be delivered to them. Sometimes they will go somewhere else, perhaps to control a piece on a board, a first person shooter, a space ship, or an animated sprite wondering through 2d world.
There's a least a couple of ways to handle this. Since the browser doesn't know about your user elements they won't automatically get events delivered to them. You can add artificial containing elements like a div element into your tree with the canvas as a child. Then you can register for the event in the artificial div and if the canvas doesn't cancel the event it will bubble up to the artificial div. I don't talk about that one in this document.
Another way to go is to have an event manager associated with the canvas who receives all the events and decides what to do with them. User elements in the canvas register with the event manager and registers callbacks. The event manager keeps queues for each type of event and when a new event arrives dispatches it as appropriate. That's the one I'm going to talk about.
All code used here is copyright me of course, but you're welcome to use it as long as you credit me. I use a lot of stuff others like Jeff Walden, Michael Kuehl, Juan Mendes, or Gavin Kistner wrote and made available. You can get it as well as a separate script it depends on from my site. canvasutilities.js and utilities.js.
When someone tells the event manager that they want to listen for an event, the event manager puts one of these on the appropriate queue to keep track of it. The id is created by the event manager and is used by the client later when they want to quit listening. The event type is something like 'mousedown', or 'click', hit is a callback to the client that's called like hit(x,y). The x and y are in canvas coordinates rather than browser coordinates. The client returns true if they want the event, else false. callback is of course the routine to be called with the event if hit returns true. It's called like - callback(x,y,e) where x and y are in canvas coordinates and e is the event as sent from the browser. You'll see it used in a bit.
This is the beginning of the constructor for the eventManager, it takes one argument, canvasManager. The only requirement for that is that it has to be an object with a member canvas so we can get to the canvas when we need to translate the browser's coordinates to canvas coordinates. We save a copy of this in a variable self so closure will let methods that get called from external contexts find the eventManager. id starts at 0 and goes up by one everytime a new listener request comes in. The queues Object is used an an associative list of arrays. You use the name of the event type to get to the array for that type. We save a copy of the canvasManager that was passed in.
The listen method is used to tell the eventManager that you'll be attentive to a particular type of event. You pass in the event type you care about, a callback hit, that will be called with an x,y pair in canvas coordinates, and you will be responsible to decide if that particular event will apply to you. Return true if so. Finally, you pass in the callback to be called if hit returns true.
First you look up the queue. If this is the first time that a request to listen for this particular event has arrived, the queue will not yet exist. In that case we create a new Array and assign as the queue. Then we walk the queue to see if this request duplicateis an existing one. If so, we'll just return the id of the found request.
If the request wasn't found we creat a new eventListener and add it to the list. The id is the current value of id. If the queue was empty, we call Michael Kuehl's hookEvent from our utilities.js to ask the browser to start sending us the events.
Finally we bump up the value of id to be ready for the next time, and then we return the value of id before it was bumped up.
I look up the queue in queues. If it's null then the client wasn't listening, and is apparently delusional. We'll just return. Otherwise, we walk the queue looking for the right id. When it's found, we remove it (the remove is one added to Array.prototype, and created by Jeff Walden). If the queue is now empty, we call Michael Kuelh's unhookEvent from our utilities.js unless the event is either mouseover or mouseout which we need to track for our own purposes as you'll see a little later one.
Then we get the queue from queues, and then set passon to true. passon, is returned at the end, the convention from an event handler, is that if you return false, the event should not continue bubbling. If you return true it continues on.
If the queue exists, then there are clients listening for this event, and we walk through them in a for loop and for each we call their hit routine. If it returns true, then we call their callback. If their callback returns false, we set passon to false to remember.
If we're delivering to them some interaction event then we're going to remember their callback in our variable mousefocusedCB. The purpose of this is that one something starts getting events, they often want to keep getting them even if the mouse isn't over their part of the UI. An example would be a slider. Once you click on the slider, you want the slider to keep moving with the mouse until you release it mouse button, even if you don't stay over the slider.
Next comes the else for the call to hit. If the hit returned false, we check to see if they have the focus, and if they do, and the event is one of the types of events we pass to whoever has the focus, then we call their callback anyway. There are two kinds of things we pass on. The first type is basic movement things like mousemove or mousescroll, or keydown. The second type are things that the client will have to see to know that they are done with something like mouseup, or touchend, or mouseout. If they return false, we remember it.
Finally, if they are the one with the focus, and the event isn't one of the ongoing movement sort of events that lets them keep focus, then we take the focus away. These events would be things like touchend, mouseout, or click.
Then, ultimately, we return passon.
The last thing we do in our constructor is to call hookEvent to listen to mouseout and mouseover. We always need these events.
Something like this.eventmanager=new eventManager(this);. This would be done from inside the constructor of a class which also contained a member canvas that referred to the canvas. An example of it's use in in my Circle of Confusion tutorial over in the Photography section. The canvas widget on that page is instantiated from the CoC_Widget.js. The sliders in that widget will respond to scroll wheels, fingers, mice, and, after being clicked, cursor keys.
You can also look at The Game of Life which uses some colorful buttons that use this event manager.