简体   繁体   English

浏览器使用 FontFace 延迟加载字体

[英]Browsers lazy-loading fonts with FontFace

So, I'm developing a simple web game with the Canvas API.所以,我正在使用 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:在加载例程中,我使用 promises 来等待我需要的字体,如下所示:

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. Chrome 和 Firefox 仅在我使用fillText()时加载它们,使用默认衬线字体创建一些框架,直到字体加载,在 Chrome 中。

According to the spec the promises should only be resolved when the fonts are loaded, but it also allows for lazy loading.根据规范,promise 应该只在加载字体时解决,但它也允许延迟加载。

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.我认为FontFaceObserver在这里很适合你。 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.您仍然可以使用 JS API 或通常的@font-face CSS API 加载字体,FontFaceObserver 将在字体加载后帮助您触发其他内容。

Here's a full example combining your code and the multiple fonts example from the FontFaceObserver README:这是一个完整的示例,结合了您的代码和 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!希望这有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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