Konva - text and web-fonts, use a font loader
Photo by Immo Wegmann / Unsplash

Konva - text and web-fonts, use a font loader

The font loading process is a stumbling block for folks new to using web-fonts in conjunction with Konva.Text and in the canvas. In this short post I'll explain what the problem is, how to solve it, and provide links to sample code.

The problem

You've probably arrived here because you have problems with web-fonts in relation to Konva.Text or the HTML5 canvas. Maybe

  • you just don't see the font you expected based on what your code asked for
  • the characters in the text appear to use the anticipated font but appear cramped or gappy
  • the font seems to start off as some unwanted default then switch to the anticipated version between initial draw and refresh.

These issues all occur because fonts are resources that live outside of your main HTML page definition, and they have to be fetched to the browser before use.

Fetching a web-font file will take some time - mostly not too long, but we can't rely on it being instant.

It is highly likely that your code refers to a font that the browser has not yet loaded, and your code immediately proceeds to generate output in that font before the browser has completed loading it.

The problem is to know when the font you want is loaded and ready to use.

You may be setting up the font information in CSS font-face declaration as you would when you use web-fonts in a web page. But importantly, the fonts loaded by this route are specifically those that connect ultimately to some HTML element like a DIV or a PARA. Which means that the standard loading flow for a web page is no help at all in our desire for controlled loading of fonts for the canvas.

I know what you're thinking - we could start loading hidden or off-screen HTML elements that referenced font declarations in the CSS and thereby trigger font loading. But font loading is an async process - how would we know when it completed, or if there was an error in the font loading process?

And so we come to the answer.

The solution

The correct way to work with web-fonts in Konva.Text or the canvas is to use a font loader.

Two good options at time of writing are fontfaceobserver and the CSS Font Loading API. Follow those links for explanations and sample code.

Both of these provide a controlled font loading process with either promises or call-backs to check on loading progress, completion and errors.

Using a font loader you can set up your code to wait until the required font is present before you refer to it, ensuring that the character measurements and positioning are accurate and avoiding the symptoms listed at the top of this post.

The ultimate test of your abilities is to provide a drop-down select list of fonts that the user can apply. Behind this list you would have the necessary information to get each font from Google Fonts via the font loader. Then, when the user selects a font you would create the request to load the font, watch for its completion or errors, and display the text using the downloaded font.

The browser caches the fonts it has already used, so the costly network activity of downloading a font only happens once.

Summary

We've seen that for accurate and consistent use of web-fonts we have to use a controlled loading process so that we know for sure that the font is loaded before we refer to it, and we've got links to two such options.

Thanks for reading.

VW Oct 2024