最近在做一个项目涉及到加载第三方字体的问题,首批需要支持一百多种字体,然后首先想到的就是@fant-face,但是在实际应用中发现无法满足当前需求. 目前的项目是用canvas的一个开源库fabric.js实现图片和文字的拖动,放大,缩小,旋转等操作,需要对文字设置不同字体的功能,首先就用的@fant-face,因为之前没用过,本来以为是只要用@fant-face定义的字体文件会在页面加载就去加载字体文件,实践发现并非这样,本来还想着在选择字体的时候再去动态添加对应文字的@fant-face,后来发现只有在页面中有用到这个字体时才回去加载,那就不用那么麻烦了,直接全部写入css中. 但是又遇到了一个问题,就是在fabric.js创建的canvas画布中,只有在第一次设置字体的时候如果字体已经加载完成才能渲染成功,否则就渲染不成功,那只能想其他办法了. 然后就去搜了一大堆监控字体加载完成相关的,最后发现了一个神器document.fonts,接下来就介绍一下怎么使用.
//加载字体文件
obj格式,cssValue为自定义字体的名字,url为自定义字体的文件路径
loadFont(obj){
if(document.fonts&&!this.checkFont(obj.cssValue))
{
let that=this;
let fontFamily=obj.cssValue;
console.log(obj);
let fontFace = new FontFace(obj.cssValue, `local(\'${obj.cssValue}\'),url(\'${obj.url}\') format(\'ttf\'),url(\'${obj.url}\')`);
fontFace.load().then(function(loadedFontFace) {
document.fonts.add(loadedFontFace);
that.canvasDemo.updateTextFontFamily(fontFamily);
});
}
},
//检测字体文件是否已加载
checkFont(name){
let values=document.fonts.values();
let isHave=false;
let item=values.next();
while(!item.done&&!isHave)
{
let fontFace=item.value;
if(fontFace.family==name)
{
isHave=true;
}
item=values.next();
}
return isHave;
}
复制代码
这样就可以监控到字体加载完成的事件,然后在完成事件中去更新canvas的文字内容了.目前发现document.fonts不支持ie,在ff中会自动缓存字体文件,但是在chrome中无法缓存,刷新页面之后在使用的话document.fonts中就找不到相关的字体了,加了local()也无法缓存,目前还未解决此问题.