HTML Canvas: How to address latency between user interaction and draw events?

Go To


I'm working on a game that allows players to click on a card and drag it across the screen in any random direction. There are a total of 64 100x80 overlapping cards on a 800x800 canvas at any one time and each one is a procedural draw. As some of you probably suspect, canvas doesn't like redrawing that entire canvas for every move. To work around this, I'm utilizing a buffer canvas to draw the card and then attempting to paint that buffer canvas to the main canvas using drawImage(). To ensure there is no drawing buildup, I clear the region of the canvas associated with where I plan to drawImage() using a clearRect().

The problem I'm experiencing is that because the (x,y) coordinates used for the clearRect() and drawImage() are coming from the location of the mouse, if the user moves too fast, the coordinates will differ from the time drawImage() was last executed to the time clearRect() is called during the next draw sequence. The result is residual draw from the last sequence - proportionate to how fast the card is being dragged.

I tried maintaining the (x,y) coordinates from the drawImage() and using those (instead of the current mouse location) for the clearRect() in the next sequence. However, now instead of residual draw being shown, residual we have residual clear (erase).

Thoughts on how I can address this?

NOTE: My animation rate is handled using RequestAnimationFrame and not SetInterval().

2012-04-04 19:00
by chopperdave


Assuming your canvas is static during the drag drop operation, a pretty easy way to get a good increase in performance would be to just cache the rendering.

In other words, when a drag drop operation begins, save the current canvas into another one. Stop all rendering except for the one involved with dragging the card. Now, whenever you need to repaint, simply repaint from your copy-canvas. Since you're basically just copying from one to another, it should be pretty fast.

On each processing cycle, you would take the current position of the dragged card, fill that with data from the copy, then redraw the dragged card in the new position.

Other approaches you could try would be to use some kind of a placeholder for the drag. For example, consider using a same-sized DIV which you display while dragging. This should have the benefit of not requiring to touch the canvas while dragging and thus also run a better performance for it.

2012-04-04 19:26
by Jani Hartikainen
So like this? MouseDown Event Occurs: Draw Canvas1 w/o Card, Save Canvas1 to Cache. MouseMove Event Occurs: Draw Card to Canvas2, Draw Canvas1 to Canvas, Draw Canvas2 to Canva - chopperdave 2012-04-04 20:10
rock on - that did it. thanks mate - chopperdave 2012-04-04 21:02