最近遇到一个比较难搞定的问题,想请教下各位朋友。我相信,高手在民间,说不定我的问题就迎刃而解了。
我想做一件事情,通过 canvas 绘制文本,绘制的文本千奇百怪,主要是有自定义字体,这些字体是通过 @font-face 的形式下发的,类似这样,页面加载的时候会加载下面的内容:
如果通过 css 使用这个自定义字体,可以正常显示,符合预期:
但是如果通过 canvas 绘制时,发现绘制的结果与 CSS 不一致。打印canvas 的 context.font 结果是 10px sans-serif。说明通过 canvas 绘制字体时遇到问题,使用了默认的字体。
const demo = () => {
const canvas = document.getElementById('canvas-demo') as HTMLCanvasElement;
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
ctx.font = '40px 7011';
// 打印的是 10px sans-serif,并不是 40px 7011
console.log('demo font = ', ctx.font);
ctx.textBaseline = 'top';
ctx.textAlign = 'left';
ctx.fillText('素燕', 80, 20);
}
出现这个问题的原因,我分析了下:
1、如果打印 ctx.font 为默认值 10px sans-serif 可以判定为 canvas 绘制使用的字体参数有问题。出现这种问题原因可能是 @font-face 中的字体还没加载完,但是我用 CSS 的写法能够正常绘制。即使我加了延迟用 canvas 绘制,也不能解决问题;
2、可能是 @font-face 中的字体集里没有要渲染的字。这点我确认肯定存在的,因为我用 CSS 能够正常绘制,说明字体集没问题;
3、@font-face 的字体加载是懒加载,按说如果我用 CSS 已经加载过了字体,用 canvas 应该能正常绘制才对,这说明不是懒加载的问题;
4、我试了某些字体,用同样的方式发现 CSS 和 canvas 的渲染效果一致。这里有个疑问为何有些字体可以,有些字体不可以。
综上,我怀疑是因为 canvas 对某些自定义字体渲染支持的不够好,才会导致和 CSS 渲染的结果不一致。
但是,我不太甘心得出这个结论,所以想请教下有没有人知道这个问题的具体原因。非常感谢。
我也查看了一些资料,但是没有满意的答案:
fontfaceobserver监听字体下载
https://github.com/bramstein/fontfaceobserver
webfontloader
https://github.com/typekit/webfontloader
loading-web-fonts-with-the-web-font-loader
https://css-tricks.com/loading-web-fonts-with-the-web-font-loader/
可以让字体足够的小,抽取需要用到的字体
https://zhuanlan.zhihu.com/p/349267844
页面字体闪一下,两个标准帮到你
https://juejin.cn/post/6844903665875025928
基于 Node.js 的 WebFont 解决方案
https://article.mebtte.com/web_font_solution_by_node
css-font-loading 标准
https://drafts.csswg.org/css-font-loading/
字体加载最佳实践
https://xiaoiver.github.io/coding/2018/03/22/%E5%AD%97%E4%BD%93%E5%8A%A0%E8%BD%BD%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5.html
长按关注
素燕《前端小课》
帮助 10W 人入门并进阶前端
官网:https://lefex.gitee.io/