I have main canvas on which I draw another canvas which had a text written on it. When I saw the results, it appears that the text is rasterized and not smooth.
Here is the code I tried :-
const mainCanvas = document.querySelector('.main');
const mainCanvasContext = mainCanvas.getContext('2d');
const backgroundCanvas = document.createElement('canvas');
backgroundCanvas.width = 1000
backgroundCanvas.height = 1000
const backgroundCanvasContext = backgroundCanvas.getContext('2d');
const run = async() => {
const title = 'SQUARE'
const text = title.toUpperCase();
backgroundCanvasContext.font = '300px KulminoituvaRegular';
ctx.fillStyle = 'white';
ctx.fillText(text, 800/2, 30);
mainCanvasContext.drawImage(backgroundCanvas, 0, 0, mainCanvas.width, mainCanvas.height);
};
run();
.main {
background: blue;
}
@font-face {
font-family: 'KulminoituvaRegular';
src: url('https://www.miketaylr.com/f/kulminoituva.ttf');
}
<canvas width="1000" height="1000" class="main"></canvas>
Problem: The final text canvas draw on the main canvas has blurry / rasterized text
Here is the Final Result :-
5
Most certainly, you haven’t synchronized the canvas dimensions in your original script – resulting in a blurry/pixellated rendering.
Keep in mind canvas.width
(and height) won’t return the final width as affected by CSS. If you haven’t specified width and height as attributes for your <canvas>
element or in your script canvas.width
and canvas.height
return the default: 300×150.
In the following example I retrieve the final dimensions via canvas.getBoundingClientRect()
.
const mainCanvas = document.querySelector('.main');
const mainCanvasContext = mainCanvas.getContext('2d');
console.log('original dimensions:', mainCanvas.width, mainCanvas.height)
const backgroundCanvas = document.createElement('canvas');
const backgroundCanvasContext = backgroundCanvas.getContext('2d');
// get dimensions of main canvas
let {
width,
height
} = mainCanvas.getBoundingClientRect();
mainCanvas.width = width;
mainCanvas.height = height;
backgroundCanvas.width = width;
backgroundCanvas.height = height;
console.log('synchronized dimensions:', mainCanvas.width, mainCanvas.height)
const run = async() => {
// load font
const font = new FontFace("MatterSQ", "url('https://g.webfontfree.com/Code/WOFF/cc/c1/ccc1e1dc515b5e79736e3498cc9f0cf7.woff')", {
style: "normal",
weight: "400",
});
// wait for font to be loaded
await font.load();
// add font to document
document.fonts.add(font);
let text = 'SQUARE'
backgroundCanvasContext.font = '100px MatterSQ';
backgroundCanvasContext.fillStyle = 'white';
backgroundCanvasContext.textAlign = "center";
backgroundCanvasContext.textBaseline = "middle";
backgroundCanvasContext.fillText(text, width / 2, height / 2);
//render to main canvas
mainCanvasContext.drawImage(backgroundCanvas, 0, 0, width, height);
};
run();
.main {
width: 800px;
aspect-ratio: 16 / 9;
background: #ccc;
}
<canvas class="main"></canvas>
Besides, you need to wait for external fonts to bee fully loaded. You could use the fontFace
API like so
// load font
const font = new FontFace("MatterSQ", "url('https://g.webfontfree.com/Code/WOFF/cc/c1/ccc1e1dc515b5e79736e3498cc9f0cf7.woff')", {
style: "normal",
weight: "400",
});
// wait for font to be loaded
await font.load();
// add font to document
document.fonts.add(font);