Reputation: 98846
Whilst looking up how to draw a repeated image background onto a <canvas>
(yup, I’m new to <canvas>
), I saw there are two ways to do it:
drawImage()
in a for
loop to manually repeat the image across the <canvas>
context.createPattern()
, set the <canvas>
's fillStyle
to that pattern, and then use fillRect
to draw a rectangle containing the pattern across the whole <canvas>
.Obviously, the first thing I did was create a JSPerf test to see which was faster (“Premature Optimisation™ — It Works”):
It seems like the drawImage()
way tends to outperform the createPattern()
way, although the difference reduces with more recent browsers, and seems to disappear in the latest.
I expected the createPattern()
way to be faster though. I assumed createPattern()
would basically be doing the same thing as the manual drawImage()
method, but being built-in, would do it faster.
Any ideas why the createPattern()
method is slower? Does createPattern()
do things other than drawing the pattern image repeatedly across the shape it’s applied to? Have I just made a mistake when writing my test?
Upvotes: 4
Views: 3029
Reputation: 1
I got really frustrated trying to get my head around closures and nesting for loops in Javascript - am more experienced with VB and am starting to use JS for making fun little games.
Anyway long story short, am not sure on the efficiency scale but this did the job for me:
function body_onload(){
var canvas = document.getElementById('canvas-id');
var context = canvas.getContext('2d');
var width = canvas.width;
var height = canvas.height;
var image = new Image();
function drawBackground(){
context.fillStyle=context.createPattern(image, "repeat");;
context.fillRect(0,0,width,height);
}
image.src="grass.jpg";
image.onload = drawBackground;
}
Worked first time for me. even tried referencing an actual <img>
instead of creating a new image just using JS, the method I published here seems to be easier to work with, especially if I want to change the image, I can do that easily.
Am sure this could be more efficient. If anyone knows how, I’d love to hear!
Upvotes: 0
Reputation: 63840
I got the opposite result after some testing.
The way you made the perf test was a bit weird. I normalized it and moved the javascript code from setup to prep (where it should be)
http://jsperf.com/createpattern-vs-drawimage/2
Filling a pattern seems to be faster than the loopy drawImage in chrome, IE, Firefox (slightly), mobile chrome (galaxy nexus), iPad safari.
In addition, simply making the pattern (using fillRect with a pattern or otherwise) and caching it onto an offscreen canvas and drawing from that should be about as fast. Both methods should be faster than using a loop to call drawImage many times. I added this third way as the third snippet in the test.
What's more, just how much of a benefit there is to a pattern or a cached pattern ought to increase dramatically the more times the image is repeated. See here, for instance:
http://jsperf.com/createpattern-vs-drawimage/3
where drawing an image hundreds of times leads to createPattern being 100-200x more efficient than the drawimage loop
Upvotes: 4