views:

44

answers:

2

I've been playing around with canvas a lot lately. Now I am trying to build a little UI-library, here is a demo to a simple list (Note: Use your arrow keys, Chrome/Firefox only) As you can tell, the performance is kinda bad - this is because I delete and redraw every item on every frame:

this.drawItems = function(){
    this.clear();
    if(this.current_scroll_pos != this.scroll_pos){
        setTimeout(function(me) { me.anim(); }, 20, this);
    }
    for (var i in this.list_items){
        var pos = this.current_scroll_pos + i*35;
        if(pos > -35 && pos < this.height){
            if(i == this.selected){
                this.ctx.fillStyle = '#000';
                this.ctx.fillText (this.list_items[i].title, 5, pos);
                this.ctx.fillStyle = '#999';
            } else {
                this.ctx.fillText (this.list_items[i].title, 5, pos);
            }
        }
    }
}

I know there must be better ways to do this, like via save() and transform() but I can't wrap my head around the whole idea - I can only save the whole canvas, transform it a bit and restore the whole canvas. The information and real-life examples on this specific topic are also pretty rare, maybe someone here can push me in the right direction.

A: 

Ok, I think I got it. HTML5 canvas uses a technique called "immediate mode" for drawing, this means that the screen is meant to be constantly redrawn. What sounds odd (and slow) first is actually a big advantage for stuff like GPU-acceleration, also it is a pretty common technique found in opengl or sdl. A bit more information here: http://www.8bitrocket.com/2010/5/15/HTML-5-Canvas-Creating-Gaudy-Text-Animations-Just-Like-Flash-sort-of/

So the redrawing of every label in every frame is totally OK, I guess.

saibotd
I have updated the example (http://saibotd.com/what.html). The key to performance is to draw all text into a separate canvas and keep copying parts of it into your shown canvas via drawImage()
saibotd
+1  A: 

One thing you could try to speed up drawing is:

  • Create another canvas element (c2)
  • Render your text to c2
  • Draw c2 in the initial canvas with the transform you want, simply using drawImage

drawImage takes a canvas as well as image elements.

andrewmu
This is correct! Thank you very much! It seems odd first to spawn another canvas, but you never actually need to append it to the dom, so what gives. I have updated my demo as well.
saibotd