【NodeJS & JS】动态加载字体的各方式及注意事项;

29 篇文章 0 订阅
11 篇文章 1 订阅

首先加载字体这个需求基本只存在于非系统字体,系统已有字体不需要加载即可直接使用; 

  • 方案1:创建 style 标签,写入 @font-face{font-family: 'xxx';src: url('xxx')} 等相关字体样式;将style标签添加到body里;
  • 方案2:通过 new FontFace() 进行字体加载,然后通过相关API进行检测加载情况;

 


方案1的适用场景:适合一次性加载所需字体;自己对应功能读取字体结构信息不依赖浏览器的真实加载情况;对加载字体的延迟情况无要求;

方案2的适用场景:适合完全加载好字体再执行某功能,避免字体还原显示异常(例如我项目所用的fabric库的相关字体功能);适合按需加载字体;能完全掌握字体加载流程,提高代码可读性、功能可控性;


 代码示例仅以本人electron+vite+vue3的项目应用为例,就算是在web用也简单改下就完事了,核心一点没变;

并且案例仅以本地静态字体资源为例,不做过多的其他场景的案例代码分析省点字,如果是http请求拿到的字体资源,碰到数据格式与例子不一致的情况下,自行了解如何转为所需的格式;

方案1:通过style标签加载字体


import { basename, extname } from 'path-browserify';

const localFonts = import.meta.glob('/public/fonts/*.*');

function getFontName(fontPath: string) {
    return basename(fontPath.replace(/\\/g, '/')).slice(0, -extname(fontPath).length);
}
function loadLocalFonts() {
  // 处理软件自带的字体资源
  const fontStyle = document.createElement('style');
  let fontFace = '';
  Object.keys(localFonts).forEach((font) => {
    // 打包后路径不需要/public,所以要去掉
    font = font.replace('/public', '');

    const fontName = fontStore.getFontName(font);

    fontFace += `@font-face{font-family: '${fontName}';src: url('${font}')}\n`;
  });
  fontStyle.innerText = fontFace;
  document.body.appendChild(fontStyle);
}

方案2:通过 new FontFace() 进行字体加载


import { readFileSync, readdirSync } from 'fs';
import { isArrayBuffer } from 'lodash-es';

function isFontFile(filename: string) {
  const fontExtensions = /\.(ttf|otf|woff|woff2|eot)$/i;
  return fontExtensions.test(filename);
}

  async getDownloadFont() {

    // 获取保存字体的路径,此案例是非自己项目内自带的字体,按需自己改该行代码即可;
    const filePath = await ipcRenderer.invoke('GET_FONT_PATH');

    const files = readdirSync(filePath);
    const fontList: any[] = [];
    files.forEach((val) => {
      if (isFontFile(val)) {
        const data = readFileSync(join(filePath, val).replace(/\\/g, '/'));
        const arrayBuffer = new Uint8Array(data).buffer;
        if (isArrayBuffer(arrayBuffer)) {
          fontList.push({
            path: join(filePath, val).replace(/\\/g, '/'),
            name: val,
            buffer: arrayBuffer,
          });
        }
      }
    });
    return fontList;
  }

import { basename, extname } from 'path-browserify';


function getFontName(fontPath: string) {
    return basename(fontPath.replace(/\\/g, '/')).slice(0, -extname(fontPath).length);
}
function setDownloadedFontList() {
  window.electron?.Font?.getDownloadFont().then((res: any[]) => {
    res.forEach((val) => {
        const fontName = getFontName(val.name);
        const font = new FontFace(fontName, val.buffer);
        (document as any).fonts.add(font);
        font.loaded.then(() => {
          if (document.fonts.check(`12px ${fontName}`)) {
            // 加载完成!!!
          }
        });
    });
  });
}

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值