【问题标题】:Speed up the drawing of many points on a HTML5 canvas element加快在 HTML5 画布元素上绘制许多点
【发布时间】:2012-12-17 14:30:45
【问题描述】:

我需要在 HTML5 画布上绘制很多点,这需要很长时间。我的代码如下所示:

var points = getPoints() // Array of {x,y,color}
var ctx = canvas.getContext("2d");

for (var i = 0; i < points.length; i++) {
   ctx.fillStyle = points[i].color
   ctx.beginPath()
   ctx.arc(points[i].x, points[i].y, radius, 0, Math.PI * 2, true)
   ctx.fill() }

我想知道我可以做哪些性能调整来加快速度。我只有5种不同的颜色。例如,我是否会受益于对点列表进行即时排序以仅更改 ctx.fillStyle 5 次而不是每个点一次?

【问题讨论】:

  • 我认为这条线很慢:ctx.arc(points[i].x, points[i].y, radius, 0, Math.PI * 2, true) 尝试绘制简单的矩形,看看是否加快了速度。 (恕我直言,它应该...)
  • 我试过了,是的,它确实加快了速度。但是,我看不出这有什么帮助。
  • 我认为如果你设置一个小提琴它会更容易让人们调整它,这里有一些我能想到的修改让它更快一点(也许)-> FIDDLE ...
  • @Stewie 绘制弧线需要大量计算。填充矩形要简单得多...
  • “many”是多少,“pretty long”是多少?

标签: javascript html canvas html5-canvas


【解决方案1】:

例如,我是否会受益于对点列表进行即时排序以仅更改 ctx.fillStyle 5 次而不是每个点一次?

根据我的经验,是的 - 经常更换 .fillStyle 非常昂贵。

我的代码在画布中绘制了大量矩形,并且绘制仅具有两种不经常变化的颜色的矩形的时间明显优于使用许多频繁变化的颜色进行绘制。

无论如何,因为你只有五种不同的颜色:

  1. 创建一个可以在其中绘制五个圆圈的离屏画布
  2. 使用.drawImage() 将正确的色环blit 到目标画布中,而无需重新计算圆弧坐标
  3. points[i] 分配给循环内的局部变量,以避免反复取消引用。

在我的笔记本电脑上,这段代码在 7 毫秒内在 400x400 的画布上绘制了 3000 个圆圈:

var colours = ['red', 'green', 'blue', 'yellow', 'magenta'];
var n = colours.length;
var r = 10;
var d = r * 2;

var off = document.createElement('canvas');
off.width = n * d;
off.height = d;
var ctx = off.getContext('2d');  

for (var i = 0; i < n; ++i) {
    ctx.fillStyle = colours[i];
    ctx.beginPath();
    ctx.arc(i * d + r, r, r, 0, 2 * Math.PI);
    ctx.closePath();
    ctx.fill();
}

var canvas = document.getElementById('canvas');
var ctx2 = canvas.getContext('2d');
var t0 = Date.now();
for (var i = 0; i < 3000; ++i) {
    var c = Math.floor(n * Math.random());
    var x = Math.floor(canvas.width * Math.random());
    var y = Math.floor(canvas.height * Math.random());
    ctx2.drawImage(off, c * d, d, d, x - r, y - r, d, d);
}
var t1 = Date.now();
alert((t1 - t0) + "ms");

​见http://jsfiddle.net/alnitak/Dpgts/

【讨论】:

  • 哇,我的在 3 毫秒内完成。感人的。非常感谢!
  • @Stewie BTW,如果您的圈子不重叠,您可以使用.putImageData 加快速度。
  • 他们没有。你的意思是而不是 .drawImage()?
  • @Stewie 我试过了,但我只是试了一下,它实际上更慢。
  • 2018 年,无论是在 FF 还是 Chrome 中,arc() 函数和上下文的变化都快了很多,速度差异也没有以前那么大了。这些天来,我可以在 400 毫秒内绘制 70k r=3 个圆圈,drawImage() 版本的速度只有 2 倍。所以对于大多数应用来说,我认为已经不需要这种优化了。
猜你喜欢
  • 2014-09-23
  • 2011-12-10
  • 2011-03-01
  • 1970-01-01
  • 2011-06-17
  • 1970-01-01
  • 2016-02-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多