Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I put custom fonts into HTML5 Canvas easily?

When looking through the questions I never found a clear answer to the above. I wanted a method that worked with just about every platform. So for the benefit of the community, I thought I'd share my success in getting custom fonts to work in canvas. My main question was, What is a surefire way to get said fonts to work? I tried multiple methods such as just using a CSS stylesheet but it's a bit more complicated than that. Here's what I found:

like image 476
Brendan Avatar asked Mar 25 '15 05:03

Brendan


People also ask

How do I add custom fonts to canvas?

canvas = document. querySelector('canvas'); var myFont = new FontFace('myFont', 'url(assets/fonts/myFont/myFont. otf)'); Now we create our font object using the javascript class FontFace which receives the font family and the source.

Can I use different fonts in canvas?

While Canvas offers seven different font sizes, there is always the chance you need one more. The easiest way to do this is to: highlight the line or block of text you wish to change. select a font size other than the default of 12pt.


2 Answers

Update: This solution now works on all browsers except IE 11 and below.

Although it doesn't have complete support yet you can now use the FontFace API to explicitly load fonts before using them on a canvas.

var f = new FontFace('Font name', 'url(/path/to/font.ttf)');

f.load().then(function(font) {

  // Ready to use the font in a canvas context
  console.log('font ready');

  // Add font on the html page
  document.fonts.add(font);

  ctx.font = '48px Font name';
  ctx.strokeText('Hello world', 100, 100);

});

I can confirm that this works on Chrome 61.0.3163.100, Safari 11.0 (12604.1.38.1.7), Firefox 56.0 (all OSX) and Safari iOS 11.1.

like image 57
dave Avatar answered Sep 22 '22 10:09

dave


I'll discuss my code underneath. First off, My Javascript:

window.onload = function start() {
            canvas = document.getElementById('canvas1');
            C_Width = canvas.width;
            C_Height = canvas.height;
            cxt = canvas.getContext('2d');
            setTimeout(text_handler,200);
        }

        function text_handler() {
        console.log('made it!');
        cxt.font="20px myFont";//font size and then font family.
        cxt.fillStyle="white"; //color to be seen on a black canvas, default is black text
        cxt.fillText("TEST",(C_Width/2-200),C_Height/2); //cxt.fillText("message",x_coord,y_coord);
        }

Allow me to explain whats going on here. I have a simple window.onload function so that the canvas exists before I try to get its Id and Context. Inside my text_handler() function, I have the font size and the font family defined in one line, as well as my font color (White because I have a black canvas). Then in the canvas I draw my message, and provide an x coordinate and a y coordinate. The setTimeout(); delay may be necessary in order to give the canvas time to load the font. In the test program I wrote, I actually got the delay time down really low, though 100ms is almost unnoticeable. Another critical part of this is the CSS stylesheet:

canvas {
            background-color: black; //for white text
            font-family:myFont; //necessary
        }
        #load {
            font-family:myFont; //necessary to load font with div
            visibility: hidden; //makes div invisible but the div element forces the text to load before the canvas.
            height: 0px;
        }
        @font-face {
            font-family:myFont; 
            src: url('./Font_Path.ttf');
            } //self-explanatory

I have of course defined the font in the canvas, the body of the webpage, and a necessary hidden div. The div helps load the font. I have styles in order that the div remains invisible but it still does its job. For some reason, through my testing, I determined that the font-family style must be above the other styles in my div. Of course, you could use whatever you want. Also of course, I use @font-face for my custom font.

Here's what the HTML looks like:

<body>
    <div id="load">words</div> <!-- load font -->
    <canvas id="canvas1" width="500px" height="500px"></canvas>
</body>

As explained above, the div is necessary to load the font before the canvas can implement it. That's why I have "words" inside it.

I really hope this helps someone out because I simply couldn't find anything on it. Please ask me questions, tell me what I could have done differently in the comment section below, or just simply ways I can simplify my code. I'd appreciate the help and constructive criticism. Thanks, and happy Canvas-ing...

like image 31
Brendan Avatar answered Sep 23 '22 10:09

Brendan