I need to draw a lot of points on a HTML5 canvas, and it is taking pretty long. My code looks like this:
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() }
I am wondering what performance tweaks I could do to speed this up. I only have 5 different colors. For example, would I benefit form sorting the points list on-the-fly to change ctx.fillStyle
only 5 times instead of one time per point?
I need to draw a lot of points on a HTML5 canvas, and it is taking pretty long. My code looks like this:
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() }
I am wondering what performance tweaks I could do to speed this up. I only have 5 different colors. For example, would I benefit form sorting the points list on-the-fly to change ctx.fillStyle
only 5 times instead of one time per point?
1 Answer
Reset to default 17For example, would I benefit form sorting the points list on-the-fly to change ctx.fillStyle only 5 times instead of one time per point?
In my experience, yes - changing .fillStyle
frequently is quite expensive.
I had code that was plotting a large number of rectangles in a canvas and the time to plot rectangles with only two infrequently varying colours was significantly better than plotting with many frequently changing colours.
Anyhow, since you only have five different colours:
- Create an off-screen canvas into which you can draw five circles
- Use
.drawImage()
to blit the right colour circle into your destination canvas without having to recalculate the arc coordinates - Assign
points[i]
to an local variable inside the loop to avoid dereferencing it over and over.
On my laptop this code is drawing 3000 circles on a 400x400 canvas in 7 milliseconds:
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");
See http://jsfiddle.net/alnitak/Dpgts/
ctx.arc(points[i].x, points[i].y, radius, 0, Math.PI * 2, true)
Try drawing simple rectangles, and see if that speeds it up. (IMHO, it should...) – ppeterka Commented Dec 17, 2012 at 14:33