0

How do I load a local font on mounted:

I have the font in the assets folder and have tried this amongst other ways.

I'm using this FontFace API as i want the font to load first before using it (https://stackoverflow.com/a/36248266/66975)

mounted () {
  const myFont = new FontFace('adobe-arabic', 'url(~@/assets/Fonts/AdobeArabicRegular/AdobeArabicRegular.ttf)');

  myFont.load().then((font) => {
    document.fonts.add(font);
    console.log('Font loaded');
  });
},
tony19
  • 125,647
  • 18
  • 229
  • 307
raklos
  • 28,027
  • 60
  • 183
  • 301

2 Answers2

1

For fonts you'd ideally want to load them in via CSS, the browser will automatically handle async loading and you can even leverage preloading to guarantee that the font will be available before navigating to the page.

mounted() isn't a great place to load assets either, since the end of the mounted hook means data/the template is about to be displayed to the user. Fonts can be very large, so by the time mounted finishes up, the user might still be downloading the font, which will lead to FOUT.

If you absolutely have to load your font programmatically via javascript, then you should use Google and Typekit's WebFontLoader library: https://github.com/typekit/webfontloader. I also recommend sticking that code into a beforeCreate() hook, rather than mounted() to avoid FOUT and similar issues

Sensanaty
  • 894
  • 1
  • 12
  • 35
  • 1
    Interestingly, `beforeCreate()` doesn't necessarily prevent FOUT. – tony19 Sep 28 '21 at 22:21
  • I think I need it in mounted, I am working with canvas and need to obtain dom elements, when i use a proper url https://examaple.com/myfont.ttf it works ok.... but loading from asset folder does not work. otherwise i get it drawing in the wrong font the first time like mentioned here https://stackoverflow.com/questions/2756575/drawing-text-to-canvas-with-font-face-does-not-work-at-the-first-time – raklos Sep 28 '21 at 22:32
  • 1
    @raklos If it's local, you probably have to fetch the font using `fontPath = require("path-to-font")`, then supplying that as your url, though to be honest I've never done something like this personally, so I don't really know whether that'll work with fonts :-) – Sensanaty Sep 28 '21 at 22:40
1

Asset URLs need to be manually resolved in script using require(assetUrl), and you would have to remove the ~ prefix:

// MyComponent.vue
export default {
  mounted() {
    const fontUrl = require('@/assets/Fonts/AdobeArabicRegular/AdobeArabicRegular.ttf').default
    const myFont = new FontFace('adobe-arabic', `url(${fontUrl})`);
    //...
  }
}

However in the SFC's <style> block, the asset URL resolution happens automatically when the URL is prefixed with ~ (as you had attempted). So you could replace the above with:

// MyComponent.vue
<style>
@font-face {
  font-family: "adobe-arabic";
  src: url("~@/assets/Fonts/AdobeArabicRegular/AdobeArabicRegular.ttf");
}
</style>
tony19
  • 125,647
  • 18
  • 229
  • 307
  • This worked, just needed to remove the .default bit though. thanks. I tried adding the fontface in style block but was still having the issue. not sure if it's a canvas thing – raklos Sep 28 '21 at 22:58
  • The `.default` bit probably depends on your bundler config (in my case, it's Vue CLI's configuration of Webpack), and file size of the `.ttf`. – tony19 Sep 28 '21 at 23:00