When I draw a text in a canvas with a typeface that is loaded via @font-face, the text doesn't show correctly. It doesn't show at all (in Chrome 13 and Firefox 5), or the typeface is wrong (Opera 11). This type of unexpected behavior occurs only at the first drawing with the typeface. After then everything works fine.
Is it the standard behavior or something?
Thank you.
PS: Following is the source code of the test case
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>@font-face and <canvas></title>
<style id="css">
@font-face {
font-family: 'Press Start 2P';
src: url('fonts/PressStart2P.ttf');
}
</style>
<style>
canvas, pre {
border: 1px solid black;
padding: 0 1em;
}
</style>
</head>
<body>
<h1>@font-face and <canvas></h1>
<p>
Description: click the button several times, and you will see the problem.
The first line won't show at all, or with a wrong typeface even if it does.
<strong>If you have visited this page before, you may have to refresh (or reload) it.</strong>
</p>
<p>
<button id="draw">#draw</button>
</p>
<p>
<canvas width="250" height="250">
Your browser does not support the CANVAS element.
Try the latest Firefox, Google Chrome, Safari or Opera.
</canvas>
</p>
<h2>@font-face</h2>
<pre id="view-css"></pre>
<h2>Script</h2>
<pre id="view-script"></pre>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script id="script">
var x = 30,
y = 10;
$('#draw').click(function () {
var canvas = $('canvas')[0],
ctx = canvas.getContext('2d');
ctx.font = '12px "Press Start 2P"';
ctx.fillStyle = '#000';
ctx.fillText('Hello, world!', x, y += 20);
ctx.fillRect(x - 20, y - 10, 10, 10);
});
</script>
<script>
$('#view-css').text($('#css').text());
$('#view-script').text($('#script').text());
</script>
</body>
</html>
Use this trick and bind an
onerror
event to anImage
element.Demo here: works on the latest Chrome.
You can load fonts with the FontFace API before using it in the canvas:
The font resource
myfont.woff2
is first downloaded. Once the download completes, the font is added to the document's FontFaceSet.The specification of the FontFace API is a working draft at the time of this writing. See browser compatibility table here.
i've bumped into the issue when playing with it recently http://people.opera.com/patrickl/experiments/canvas/scroller/
worked around it by adding the font-family to canvas directly in the CSS, so you can just add
canvas { font-family: PressStart; }
I try to use FontFaceSet.load to fix the problem: https://jsfiddle.net/wengshenshun/gr1zkvtq/30
You can find the browser compatibility from https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet/load
The nub of the problem is that you are trying to use the font but the browser has not loaded it yet and possibly has not even requested it. What you need is something that will load the font and give you a callback once it is loaded; once you get the callback, you know it is okay to use the font.
Look at Google's WebFont Loader; it seems like a "custom" provider and an
active
callback after the load would make it work.I've never used it before, but from a quick scan of the docs you need to make a css file
fonts/pressstart2p.css
, like this:Then add the following JS:
I wrote a jsfiddle incorporating most of the suggested fixes here but none resolved the issue. However, I am a novice programmer so perhaps did not code the suggested fixes correctly:
http://jsfiddle.net/HatHead/GcxQ9/23/
HTML:
CSS:
JS:
Workaround I eventually gave in and, on the first load, used an image of the text while also positioning the text with the font-faces outside of the canvas display area. All subsequent displays of the font-faces within the canvas display area worked no problem. This is not an elegant workaround by any means.
The solution is baked into my website but if anyone needs I will try to create a jsfiddle to demonstrate.