1

我有很多元素和mousemove方法,在选择项目时是重绘画布的。

function redraw(ctx) { // ctx - canvas context
    if (!needRedraw) 
        return;
    ctx.save();
    ctx.clearRect(0, 0, w, h);
    drawItems(ctx);
    ctx.restore();
}

function drawItems(ctx) {
    var l = nodes.length(); // array of elements for drawing (from 100 to 100000)
    for(var i = 0; i < l; i++) {
        var item = nodes[i];
        ctx.beginPath();
        ctx.strokeStyle = colors(item.type);
        ctx.fillStyle = fill(item);
        ctx.arc(item.x, item.y, item.r, 0, Math.PI * 2, true);
        ctx.fill();
        ctx.stroke();
        ctx.closePath();
    }
}

如何优化这个过程,因为它贯穿了这个非常昂贵的所有元素?可以使用异步方法,但我不明白如何应用他?

4

4 回答 4

6

您对 的调用saverestore并且closePath在编写时不执行任何操作。删除它们。

saverestore复制所有画布状态,如果曾经使用过,应该很少使用。在完美的性能世界中,您需要使用它们的唯一原因是重置剪辑区域。

绘制一条且只有一条路径,并在最后只填充(和描边)一次。

像这样:

function redraw(ctx) { // ctx - canvas context
    if (!needRedraw) 
        return;
    ctx.clearRect(0, 0, w, h);
    drawItems(ctx);
}

function drawItems(ctx) {
    var l = nodes.length(); // array of elements for drawing (from 100 to 100000)
    ctx.beginPath(); //outside of loop!
    for(var i = 0; i < l; i++) {
        var item = nodes[i];
        ctx.moveTo(item.x+item.r,item.y); // set up subpath to be at the right point
        ctx.arc(item.x, item.y, item.r, 0, Math.PI * 2, true);
    }
    ctx.fill();     //outside of loop!
    ctx.stroke();   //outside of loop!
}

根据您正在做的事情,很可能会有更多优化,但这应该会有所帮助!

希望你的项目进展顺利。

于 2012-09-24T16:02:44.743 回答
2

一篇关于优化画布操作的好文章,其中许多可能适用于您。

可能最容易开始的是将beginPath()andclosePath()调用移出循环,而是moveTo()在段之间使用,以及将画布从屏幕上绘制出来,然后将其复制到显示画布上。

于 2012-09-24T13:20:03.523 回答
1

您还可以反转您的循环,假设可以以相反的顺序绘制所有内容,因为 jsperf 显示这更快。while 循环甚至更快。

例子

var i = nodes.length();
while (i--) {
    // ...do stuff...
}
于 2012-09-24T21:11:20.233 回答
1

另一个性能提示:缓存您的 Math.PI * 2 结果。

事实上,javascript 是PI从一个对象中获取,然后将其相乘。该值始终相同,因此只需添加一个常量

例子

const PI_TIMES_TWO = 6.28; //or whatever degree of accuracy you want.

...

ctx.arc(item.x, item.y, item.r, 0, PI_TIMES_TWO, true);
于 2012-09-25T02:08:07.313 回答