Skip to content

Instantly share code, notes, and snippets.

@alexeypegov
Last active January 24, 2022 18:38
Show Gist options
  • Save alexeypegov/86acc036d9e2aff638d50660bb100733 to your computer and use it in GitHub Desktop.
Save alexeypegov/86acc036d9e2aff638d50660bb100733 to your computer and use it in GitHub Desktop.
Compare performance of fillText() vs drawImage() for HTML5 Canvas
// jshint esnext:true
// noprotect
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
function init(el, width, height) {
const _el = el ? el : document.createElement('canvas');
if (!el) {
$('body').append(_el);
}
const pixelRatio = window.devicePixelRatio || 1;
const ctx = _el.getContext('2d');
const el$ = $(_el);
_el.width = pixelRatio * parseFloat(width);
_el.height = pixelRatio * parseFloat(height);
_el.style.width = width + 'px';
_el.style.height = height + 'px';
ctx.scale(pixelRatio, pixelRatio);
ctx.imageSmoothingEnabled = false; // magic!
ctx.msImageSmoothingEnabled = false; // magic!
return ctx;
}
function genText(len) {
let text = '';
for(let i = 0; i < len; i++) {
text += ALPHABET.charAt(Math.floor(Math.random() * ALPHABET.length));
}
return text;
}
function generate(num, maxx, maxy, len) {
const a = [];
for (let i = 0; i < num; i++) {
a.push({text: genText(len), x: Math.random() * maxx, y: Math.random() * maxy });
}
return a;
}
function fillText(data) {
return (ctx) => {
for (let i = 0; i < data.length; i++) {
const o = data[i];
ctx.fillText(o.text, o.x, o.y + 9);
}
};
}
function drawImage(data) {
const cache = {};
return (ctx) => {
const draw = (s, x, y) => {
let buffer = cache[s];
if (!buffer) {
buffer = document.createElement('canvas');
const bctx = init(buffer, 300, 12);
bctx.fillText(s, 0, 9);
cache[s] = buffer;
}
ctx.drawImage(buffer, x, y, 300, 12);
};
for (let i = 0; i < data.length; i++) {
const o = data[i];
draw(o.text, o.x, o.y);
}
};
}
function log(msg) {
$('body').append($('<p>' + msg + '</p>'));
}
function doTest(name, repeats, f) {
const ctx = init(null, 400, 400);
f(ctx); // cache warmup
const s = new Date().getTime();
for (let i = 0; i < repeats; i++) {
ctx.clearRect(0, 0, 400, 400);
f(ctx);
}
const e = new Date().getTime();
log(name + ' time: ' + (e - s));
};
$(function() {
const repeats = 100;
const data = generate(100, 100, 400, 50);
doTest('fillText', repeats, fillText(data));
doTest('drawImage', repeats, drawImage(data));
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment