1

JSFiddle: https://jsfiddle.net/crfyv9bj/

In this fiddle, I'm using Paper.JS to draw text in the custom "Roberto Mono" Font.

I followed all the tips to "initialize" the custom font in an empty/dummy DIV before using Paper.JS, listed here: https://stackoverflow.com/a/72504869/1005607 , https://stackoverflow.com/a/24936013/1005607 .

However, as you can see in this fiddle, even with this empty/dummy DIV,

  • Firefox: Works instantly, auto-loads the font
  • Chrome: DOES NOT AUTO-LOAD THE FONT: Resizing the window is necessary to see the font
  • Edge: DOES NOT AUTO-LOAD THE FONT: Resizing the window is necessary to see the font

You can double-click the title bar to resize the window and only then will PaperJS display the correct custom font in Chrome and Edge. What's going on here? Can someone advise?

<!-- This is an empty/dummy DIV to "initialize" the font, STILL DOESN'T HELP -->
<div style="display: none; font-family: 'Roboto Mono';"></div>
<!-- Canvas -->
<canvas id="mycanvas" resize></canvas>

JS

    canvasElem = $('#mycanvas').get(0);
  paper.install(window);
    paper.setup(canvasElem);
  
  // Draw Text
        var text = new paper.PointText(new paper.Point(50, 50));
        text.justification = 'center';
        text.fillColor = 'red';
        text.fontFamily = 'Roboto Mono';
        text.fontSize = '30px';
        text.fontWeight = 'bold';
        text.content = 'This is a test 1234567890';
    paper.view.draw();
gene b.
  • 10,512
  • 21
  • 115
  • 227

2 Answers2

1

I found the solution on the PaperJS forum: There is some kind of timing issue where the font is not loaded before drawing. They discuss it in this thread. They suggest using a small JS library like FontFaceObserver to ensure webfonts are properly loaded first. You wrap your draw code in FontFaceObserver's font.load().then(..) (or use $.when(f1,f2,f3).done(..) if you have multiple fonts to load).

JSFiddle with working code: https://jsfiddle.net/3x458h6d/

Note: Originally I thought that I just had to add an empty/dummy DIV referencing the custom font somewhere above the Canvas. This was suggested here and here. It did help in Firefox, but Chrome/Edge were still not showing the font on startup. I had to use the FontFaceObserver solution above.

<div id="headerPanel">
    Text
    <!-- Note this manual reference to "myCustomFont" used in an unrelated earlier DIV in the HTML,
         in this case on an invisible space -->
    <div style="font-family: myCustomFont">&nbsp;</div>
</div>
 
<div id="canvasPanel">
    <canvas id="canvas" resize></canvas>
</div>
gene b.
  • 10,512
  • 21
  • 115
  • 227
1

You need to wait until the font is loaded - otherwise the canvas text is rendered in fallback font.

You can use the natively supported FontFace() method and wrap your drawing function in a async function like so:

canvasElem = $("#mycanvas").get(0);
paper.install(window);
paper.setup(canvasElem);

// Draw Text
loadFontsAndDraw();

async function loadFontsAndDraw() {
  const font = new FontFace("Roboto Mono", "url(https://webapps1.chicago.gov/cdn/uswds-2.2.1/fonts/roboto-mono/roboto-mono-v5-latin-regular.ttf)", {
    style: "normal",
    weight: "400",
    stretch: "normal",
  });
  // wait for font to be loaded
  await font.load();
  // add font to document
  document.fonts.add(font);
  
  // start drawing
  var text = new paper.PointText(new paper.Point(50, 50));
  text.justification = "center";
  text.fillColor = "red";
  text.fontFamily = "Roboto Mono";
  text.fontSize = "30px";
  text.fontWeight = "bold";
  text.content = "This is a test 1234567890";
  paper.view.draw();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/paper.js/0.12.17/paper-full.min.js"></script>
<canvas id="mycanvas" resize></canvas>
herrstrietzel
  • 11,541
  • 2
  • 12
  • 34
  • 1
    BTW: this issue is not specific to paper.js. Any canvas drawing is affected by this issue. Here's also [modified version of this helper method](https://stackoverflow.com/questions/13362569/is-it-possible-to-load-truetype-fonts-using-javascript/74633595#74633595) - it can load an array fonts and run a drawing function as callback. However, nothing wrong using [FontFaceObserver](https://fontfaceobserver.com) is a great library! – herrstrietzel Dec 09 '22 at 17:48