基于 @font-face 加载
2024年08月06日
一、认识
二、动态加载字体文件
需求描述
: 字体包体积巨大, 基本上都在几M
左右。 所以,在以下场景需要考虑按需加载字体:
- 场景一: 实时编辑一个
DOM
元素, 可以切换字体。如果直接将全部字体写入到样式文件中,IE
浏览器首先会下载全部注册声明的字体,即使未使用该字体。谷歌等浏览器实现了按需加载字体文件的功能。但是我们在使用html2-canvas
或者dom-to-image
第三方DOM
转Image
的时候, 会下载完全部字体,然后再开始解析、转化, 增加了DOM
转Image
的时间。
解决方案: 当需要加载字 体时,向 DOM
添加 @font-face
,动态加载字体。
实现如下:
const lazyLoadFontFamily = (fontFamily: string) => {
if (!fontFamily) {
return;
}
const documentStyle = document.createElement('style');
const fontFace = `
@font-face{
font-family: ${fontFamily};
src: url(${currentCdnUrl}custom-course-cover/fonts/${fontFamily}.ttf);
}
`;
documentStyle.appendChild(document.createTextNode(fontFace));
document.head.appendChild(documentStyle);
};
但是这里存在一个问题,由于请求接口需要一定的时间,文字会出现先空白一段时间后显示的现象。这种现象被称之为 FOIT (Flash Of Invisible Text)
。我们需要寻找优化办法。 font-display
属性在 CSS
层面上提供了此类问题的解决方法。使用 font-display: swap
我们可以采用先使用系统默认字体,在中文字体下载完成后替换。
三、动态加载具体字体
解决方案: 当需要加载字体时,向 DOM
添加 @font-face
,动态加载字体。
实现如下:
- Web
- Node
const lazyLoadFontFamily = (fontFamily: string) => {
if (!fontFamily) {
return;
}
const documentStyle = document.createElement('style');
const fontFace = `
@font-face{
font-family: ${fontname};
src: url("http://xxxx:8080/api/webfont?font=${fontname}&text=${encodeURIComponent(text)}`;
documentStyle.appendChild(document.createTextNode(fontFace));
document.head.appendChild(documentStyle);
};