简体   繁体   中英

Browsers lazy-loading fonts with FontFace

So, I'm developing a simple web game with the Canvas API. I need to draw characters in the canvas using specified fonts.

In the loading routine, I use promises to wait for the fonts I need, like this:

Promise.all([
    (new FontFace("LCD Solid", "url('assets/LCD_Solid.ttf')")).load().then((font)=>{
        document.fonts.add(font)
    }, (err)=>{
        throw {type: "font_loading_err", fontName: "LCD Solid", DOMException: err}
    }),
    (new FontFace("Conformity", "url('assets/Conformity.ttf')")).load().then((font)=>{
        document.fonts.add(font)
    }, (err)=>{
        throw {type: "font_loading_err", fontName: "Conformity", DOMException: err}
    }),
]).then(loadGame, oops)

The promises are resolved, but not loaded. Chrome and Firefox only load them when I use fillText() , originating some frames with the default serif font, until the font loads, in Chrome.

According to the spec the promises should only be resolved when the fonts are loaded, but it also allows for lazy loading.

Is there any way to avoid lazy-loading the fonts and force the browser to load them at that moment?

I think FontFaceObserver could work well for you here. You can still load the fonts using the JS API or the usual @font-face CSS API, and FontFaceObserver will help you trigger something else when the font has loaded.

Here's a full example combining your code and the multiple fonts example from the FontFaceObserver README:

<canvas id="js-canvas"></canvas>
<script src="https://unpkg.com/fontfaceobserver@2.1.0/fontfaceobserver.standalone.js"></script>
<script>
var exampleFontData = {
  'Family A': { weight: 400, src: 'url(assets/FamilyA-Regular.woff2), url(assets/FamilyA-Regular.woff)' },
  'Family B': { weight: 400, src: 'url(assets/FamilyB-Regular.otf)' },
  // Etc.
}

var observers = []
var fonts = []

// Make one Observer along with each font
Object.keys(exampleFontData).forEach(function(family) {
  var data = exampleFontData[family]
  var obs = new FontFaceObserver(family, data)
  var font = new FontFace(family, data.src)

  observers.push(obs.load())
  fonts.push(
    font
      .load()
      .then((f) => {
        document.fonts.add(f)
      }, (err) => {
        throw {type: "font_loading_err", fontName: family, DOMException: err}
      })
  )
})

Promise.all(fonts)
.then(() => {
  console.log('Use the canvas')
  var canvas = document.getElementById('js-canvas')
  canvas.width = 750
  canvas.height = 500
  var ctx = canvas.getContext('2d')

  ctx.font = '36px "Family A"'
  ctx.fillText('HELLO USING FONT', 20, 50)

  ctx.font = '36px "Family B"'
  ctx.fillText('Hello using font', 20, 150)
}, (err) => {
  console.error(err)
})
</script>

在画布上使用字体的结果。

Hope that's helpful!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM