Question

)

I have a small web-application which uses jquery and jcanvas (http://calebevans.me/projects/jcanvas/) to print some shapes onto a canvas.

It's basically a map. The user can zoom into it and drag it around and whenever he does so everything has to be drawn again.

As you may see in the code below I remove and recreate layers pretty often (whenever the user drags the map, zooms or resizes his window). I need the layers to handle hover- and click-events. My question is whether there is a big performance impact of this way to handle events in comparison to other solutions. If this is the case, how could I optimize my performance?

var posX = 0, posY = 0;
var zoom = 100;
var points = []; //array of up to 1000 points retrieved by ajax

function draw(){
    $("canvas").removeLayers();
    $("canvas").clearCanvas();


    var xp, yp, ra;
    var name;

    $.each(points, function(index) {
        xp = (this["x"]-posX)/zoom;
        yp = (this["y"]-posY)/zoom;
        ra = 1000/zoom;
        $("#map").drawArc({
            layer:true,
            fillStyle: "black",
            x: xp, 
            y: yp,
            radius: ra,
            mouseover: function(layer) {
                $(this).animateLayer(layer, {
                      fillStyle: "#c33",
                      scale: 1.0
                    },200);
            },
            mouseout: function(layer) {
                $(this).animateLayer(layer, {
                      fillStyle: "black",
                      scale: 1.0
                    },200);
            },
            mouseup: function(layer){
                context(index,layer.x,layer.y);
            }
        });
    }); 

}

Thank you for your time :-)

Was it helpful?

Solution

Optimization is in general a case-to-case thing but I'll try to give some general points for this case:

  • Keep operations to a minimum
  • Creating and removing "layers" (canvas elements) are costly operations - try to avoid if possible.
  • Rather move content around using drawImage() on itself or use clearRect() if you need to clear the whole canvas.

The same with a little more details:

You can for example use drawImage() to move the content to one of the sides, if we wanted to move everything to the left by 10 pixels we could do:

context.drawImage(canvas, 10, 0, canvas.width - 10, canvas.height,
                          0, 0, canvas.width - 10, canvas.height);

This will clip only the part we want to move/scroll and then redraw it in the new position.

Finally draw in the 10px gap at right with new graphics (you would probably want to cache the width and height but frankly, in the modern JavaScript engines this does not matter so much anymore as it did in the past). Test your points to see what points actually needs to be drawn to avoid drawing all of them again which otherwise renders this step pointless.

If you want to clear the canvas, rather than removing the canvas element and create a new canvas use the method clearRect() or use fillRect() if you want a pattern, color etc. Removing and creating elements are a costly operation from a optimization perspective especially if they affect the browser's flow (if it need to reflow the content). It triggers a bunch of operations from layout, css parsing, repaint etc. Reuse if you can.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top