浏览器使用 FontFace 延迟加载字体
Browsers lazy-loading fonts with FontFace
因此,我正在使用 Canvas API 开发一个简单的网页游戏。我需要使用指定的字体在 canvas 中绘制字符。
在加载例程中,我使用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)
承诺已解决,但未加载。 Chrome 和 Firefox 仅在我使用 fillText()
时加载它们,使用默认衬线字体创建一些框架,直到字体加载,在 Chrome.
根据 the spec 承诺应该只在加载字体时解析,但它也允许延迟加载。
有没有办法避免延迟加载字体并强制浏览器在那个时候加载它们?
我认为 FontFaceObserver 在这里很适合您。您仍然可以使用 JS API 或通常的 @font-face
CSS API 加载字体,FontFaceObserver 将在字体加载后帮助您触发其他内容。
这是一个完整的示例,结合了您的代码和 FontFaceObserver 自述文件中的多种字体示例:
<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>
希望对您有所帮助!
因此,我正在使用 Canvas API 开发一个简单的网页游戏。我需要使用指定的字体在 canvas 中绘制字符。
在加载例程中,我使用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)
承诺已解决,但未加载。 Chrome 和 Firefox 仅在我使用 fillText()
时加载它们,使用默认衬线字体创建一些框架,直到字体加载,在 Chrome.
根据 the spec 承诺应该只在加载字体时解析,但它也允许延迟加载。
有没有办法避免延迟加载字体并强制浏览器在那个时候加载它们?
我认为 FontFaceObserver 在这里很适合您。您仍然可以使用 JS API 或通常的 @font-face
CSS API 加载字体,FontFaceObserver 将在字体加载后帮助您触发其他内容。
这是一个完整的示例,结合了您的代码和 FontFaceObserver 自述文件中的多种字体示例:
<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>
希望对您有所帮助!