JSFiddle - React, Tailwind, and code Playground
HTML
<canvas id="canvas1" width="500" height="500"></canvas>
JavaScript
var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');
var fontCache = '';
function VerticalPanel() {
this.children = [];
}
VerticalPanel.prototype.draw = function(x,y) {
// clip the panel's space (useless clip for sake of example)
ctx.save();
ctx.beginPath();
ctx.rect(0,0,500,500);
ctx.clip();
// Draw panel's children
var l = this.children.length;
for (var i = 0; i < l; i++) {
var child = this.children[i];
child.draw(x,y);
}
ctx.restore(); // this restore is going to stop any text objects in the next panel from taking advantage of the cache because it resets ctx.font. But it is needed because there is no other way to clear clipping regions.
}
function TextChild(text) {
this.text = 'default';
this.font = '32px sans-serif';
if (text) this.text = text;
}
TextChild.prototype.draw = function(x,y) {
// set font if different from cache
if (fontCache !== this.font) {
ctx.font = this.font; // it would be nice if this only happened once
fontCache = this.font;
}
// another way of looking at the same problem is to cache this way:
/*
if (ctx.font !== this.font) {
ctx.font = this.font; // it would be nice if this only happened once
console.log('occured'); // but happens 2 times
}
*/
// clip the font's space (useless clip for sake of example)
// This clip does not interfere with the problem discussed.
ctx.save();
ctx.beginPath();
ctx.rect(0,0,500,500);
ctx.clip();
ctx.fillText(this.text, x, y);
ctx.restore();
}
// Draw two nested objects that should have the same font but do not
var p = new VerticalPanel();
p.children = [new TextChild('one')];
var p2 = new VerticalPanel();
p2.children = [new TextChild('two')];
p.draw(50,50);
p2.draw(150,50);