I just started playing with the HTML5 canvas and I was hoping to make a couple games with it. However, as soon I started rendering the mouse coordinates to it, it grinded to a near halt:
http://jsfiddle.net/mnpenner/zHpgV/
All I did was render 38 lines and some text, it should be able to handle that, no?
Am I doing something wrong? I'd like to be able to render at lest 30 FPS, but for something like this I would expect it to be able to draw 1000s of times.
Or am I just using the wrong tool for the job? Is WebGL up for the task? Why would one be so much slower than the other?
String.prototype.format = function() {
var args = arguments;
return this.replace(/\{(\d+)\}/g, function(m, n) {
return args[n];
});
};
var $canvas = $('#canvas');
var c = $canvas[0].getContext('2d');
var scale = 20;
var xMult = $canvas.width() / scale;
var yMult = $canvas.height() / scale;
var mouseX = 0;
var mouseY = 0;
c.scale(xMult, yMult);
c.lineWidth = 1 / scale;
c.font = '1pt Calibri';
function render() {
c.fillStyle = '#dcb25c';
c.fillRect(0, 0, scale, scale);
c.fillStyle = '#544423';
c.lineCap = 'square';
for (var i = 0; i <= 19; ++i) {
var j = 0.5 + i;
c.moveTo(j, 0.5);
c.lineTo(j, 19.5);
c.stroke();
c.moveTo(0.5, j);
c.lineTo(19.5, j);
c.stroke();
}
c.fillStyle = '#ffffff';
c.fillText('{0}, {1}'.format(mouseX, mouseY), 0.5, 1.5);
}
render();
$canvas.mousemove(function(e) {
mouseX = e.clientX;
mouseY = e.clientY;
render();
});
<canvas id="canvas" width="570" height="570"></canvas>
Here's the code made much better.
http://jsfiddle.net/zHpgV/3/
Here's a breakdown of the things that you should take into consideration that I changed:
beginPath
. This is by far the biggest performance killer here. You're ending up with a path with thousands and thousands of line segements that never gets cleared.render
is stroke
. You do not need to call lineTo/moveTo
ever again, and certainly not continuously. See note 1.Note 1: If you plan to have more than one path in your application then you should probably cache paths like this one since they never change. I have a a tutorial on how to do that here.
Of course, if you are doing all of this to just make a background, it should be saved as a png and you should be using a CSS background-image.
Like so: http://jsfiddle.net/zHpgV/4/
Then suddenly your render routine is rather small:
function render() {
c.clearRect(0, 0, scale, scale);
c.fillText('{0}, {1}'.format(mouseX, mouseY), 0.5, 1.5);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With