87241641 2019-07-30
最近在做一个项目时,遇到了这样一个问题:网页大标题要用设计师指定的中文字体,该字体文件比较大,浏览器加载字体文件的过程中是不会显示使用该字体的文本的,于是出现了初次打开网页时有一段时间“No title”的BUG。
针对该问题,笔者能想到以下几种解决方案(欢迎补充):
结合项目特点,最终选择方案5。
整个过程逻辑非常简单:首先标题所用的class在CSS中被定义了一个最接近目标字体的安全字体,然后等待字体文件加载,加载完成后将标题的class换成自定义字体的class。
首先设好两个CSS属性,一个是用最接近目标字体的安全字体,用于默认字体,第二个是自定义字体:
/* 定义字体 */ @font-face{ font-family: Lanting_light; src: url("../res/font/goDieDesigner.woff"); } /* 安全字体,用于默认 */ .lanting_l{ font-family: Arial, Helvetica, sans-serif; } /* 自定义字体 */ .lanting_light{ font-family: "Lanting_light",Arial, Helvetica, sans-serif; }
元素设置成默认字体:
<p class="lanting_l"> 我是一段可爱的文字,啾咪~ </p>
写一个函数,用于替换元素的class,在字体文件加载完成后执行它:
function onLoadedFont() { ele = document.getElementsByClassName("lanting_l"); for (let i = 0; i < ele.length; i++){ ele[i].classList.add("lanting_light"); ele[i].classList.remove("lanting_l"); } }
接下来是整个问题的核心:如何判断字体文件已被加载?
一个html元素,可以用监听load事件来判断加载,但字体不是html元素,无法监听。
再来看一下需求,字体文件是从用户打开页面时就要开始加载了,所以只要让字体一开始就加载,然后监听window.load事件就好了:
window.addEventListener("load",onLoadedFont);
PS:这里不太严谨,可能会有其他大体积资源加载拖慢load事件,所以大文件最好用lazyload。MDN提供了一个属性可以判断字体加载,但是目前兼容性还有一些问题,这里就先不用了,感兴趣的可以看一下这里。小弟才疏学浅,如有大神知道其他监听字体文件加载的方法,还请留言告知,谢谢~
然后就是要做些什么让字体文件一开始就去加载了,要知道不同浏览器什么时候会去加载一个字体,可以参考这篇文章。
在HTML中创建一个文本标签,让它去用这个需要被加载的字体,并且让这个文本不要出现在视窗中:
<h1 class="Lanting_light" style="position: fixed;left:calc(-1000% - 5000px)">字体</h1>
到这里,整个功能就完成了。
总结一下,这个方案可以让字体文件没有加载完的时候,先用一个接近的安全字体让文本先显示出来,待字体加载完后再换字体,核心的点是监听字体文件的加载,因为MDN上提供的document.font是一个实验性功能,兼容性不是很好,所以这里用了投机取巧的办法去监听window.load,可能会被其他大文件阻塞,也会拖慢监听window.load的其他函数,所以在项目中还是要取舍,没有完美的方案,只有最合适的方案。