Angular 10 动态字体实现疑问:能否读取assets/fonts目录及实现非SCSS声明的动态字体
Angular 10 动态字体实现问题解答
首先明确:你当前尝试的写法完全不生效的核心原因是,ngStyle仅支持绑定常规行内CSS属性,根本无法解析、注入@font-face这类全局CSS自定义规则,属于原理层面的不兼容,不是代码写错了的问题。
两个核心疑问的对应实现方案
1. 关于读取assets/fonts目录下文件列表的问题
- 浏览器端的前端代码没有权限直接枚举、遍历静态资源目录的文件列表,这是浏览器安全机制的硬性限制,和Angular框架无关。
- 可落地的替代实现:
- 字体文件是开发阶段就固定的场景:直接在前端代码里手动维护字体名称、对应路径的映射表即可,不需要动态扫描目录
- 需要动态获取文件清单的场景:通过后端接口返回字体目录的扫描结果,由后端服务读取服务器上的字体目录文件列表,接口将元数据返回给前端使用
- 生产构建注意事项:Angular默认在打包时,只会把assets目录下被代码显式引用的文件输出到最终dist产物里,如果没有在代码中写对路径,哪怕文件存在于本地assets目录,生产环境也会找不到资源。
2. 关于无需SCSS预声明的动态字体实现
完全可以实现,不需要提前在SCSS里写死@font-face规则,核心逻辑是动态向页面全局样式表注入@font-face规则,替代SCSS预编译的静态声明,具体实现:
- 写一个通用的字体注入方法,直接调用原生DOM的样式表接口:
/** * 动态注入@font-face规则 * @param fontName 注册的字体名称 * @param fontPath 字体文件的可访问路径 */ registerDynamicFont(fontName: string, fontPath: string) { const globalStyleSheet = document.styleSheets[0] as CSSStyleSheet; const fontRule = ` @font-face { font-family: "${fontName}"; src: url("${fontPath}"); } `; // 将规则追加到全局样式表末尾 globalStyleSheet.insertRule(fontRule, globalStyleSheet.cssRules.length); }
- 注册完成后,就可以正常通过
ngStyle绑定常规字体属性了,你之前的场景改造如下:
// 组件初始化时先注册字体 ngOnInit() { this.registerDynamicFont('DIN Office Medium Italic', 'assets/fonts/DINOffc-MediIta.ttf'); } // 合法的ngStyle绑定,只写常规CSS属性,不要再放@font-face配置 testFont = { fontFamily: 'DIN Office Medium Italic' }
- 针对你已经实现的用户上传字体场景,只需要把上传完成后返回的字体资源路径传给
registerDynamicFont方法即可,全程不需要任何SCSS预配置,上传完成字体即可全局生效。
常见踩坑点
- 千万不要把
@font-face配置塞到ngStyle的对象里,行内样式不支持这类全局规则,必须单独注入到页面样式表中 - 动态注入的字体规则和SCSS写的规则效果完全一致,全局生效,所有页面元素都可以调用
- 如果是跨域加载字体资源,需要确保资源服务器配置了允许跨域的CORS规则,否则浏览器会拦截字体加载
内容的提问来源于stack exchange,提问作者Asaf Bello
相关产品推荐
相关产品推荐

