Search code examples
javascriptreactjswebfontskonvajsreact-konva

Using WebFontLoader with React Konva causes text offsets?


I am attempting to draw some text data on a canvas, using a web font, with the React Konva canvas library. I am loading the web fonts using the WebFontLoader library.

There is of course a short delay before the fonts are fully loaded. However, once the font is loaded, the text is drawn in an incorrect position, and does not correct itself until it is redrawn.

I have noted that this issue only occurs for text which is aligned center or right, and left-aligned text has no such issue.

I have not found any other posts discussing this issue and how it can be resolved. Creating a ref to the component and calling draw() or forceUpdate() with the WebFontLoader after the fonts have finished loading does not cause the element to readjust, only modifying its contents does.

I have created a minimal reproducible example on CodeSandbox: https://codesandbox.io/s/react-konva-webfonts-6engr

And here is a GIF demonstrating the issue.

Demonstration

Note the text's position relative to the line, which has a static position. The text first loads in the wrong font (note that in my full application I have functionality to hide the canvas until fonts and images load), then changes to the correct font, but is in an offset position, and does not correct itself until the text box is modified.

I'd like to see either an alternative to WebFontLoader which loads the fonts in a way Konva can understand, or code that forces the Konva canvas to redraw itself.


Solution

  • Konva.Text needs to recalculate char positions when the font is loaded. But it is not doing that automatically on loading. And currently, there is no API to force the recalculation manually with some method.

    But you can force recalculating of the internal state by changing text attributes (such as text or fontFamily).

    One of the ways to do that is just fallback to default font until the original one is not loaded:

    <Text
      text={textData}
      fontFamily={loaded ? 'Roboto' : 'Arial'}
      align="right"
    />
    

    Demo: https://codesandbox.io/s/react-konva-webfonts-kswgl