因为一般项目中不需要用到所有字体,所以需要将需要的字体在字体包提取出来重新打字体包
我选择的压缩字体方式是 :使用fontmin进行字体压缩
fontmin官网为: https://blog.ipsfan.com/4298.html 可自行查看介绍以及相关api
为了以后操作方便,所以准备将压缩字体做成脚本化方式
首先确定一下目录结构,如下图
bigFonts文件夹:用于存放原始字体;
fonts.sh:是shell执行脚本(因为使用的是mac);
node文件夹 :用于存放执行的js脚本
node_modules:文件夹是压缩字体支持环境
package-lock.json:支持环境的json脚本
使用方式:将原ttf字体资源放入bigFonts文件夹中,将ttf字体修改为需要的名字(ru:font.ttf)。执行font.sh文件即可将压缩后的字体文件放入项目resource/assets/fonts目录下。
首先在nodeJs目录下有4个文件,如下图:
getTxt.js文件是读取文字的js脚本,将我们项目中的文字读取出来,放入output.txt文件中。
minFont.js文件是将output.txt文字按照bigFonts中的ttf文件格式输出新的字体文件
getTxt.js如下
var fs = require("fs")
var path = require('path')
var readline = require('readline');
function getWordAndOutput(url,paraStr)
{
var list = url;
for(var j in list){
var arr = list[j];
for(var i in arr)
{
fs.appendFile('nodeJs/output.txt',arr[i],'utf8',function(err)
{
if(err)
{
console.log(err);
}
});
}
}
}
function getFiles(url, ext)
{
fs.unlink('nodeJs/output.txt',function(err) {
if(err){
console.log(err);
return false;
}
console.log('删除文件成功');
});
fs.readdir(url,function(err, files)
{
if (err)
{
return console.error(err);
}
files.forEach( function (file)
{
fs.stat(url+file, (err, stats) =>
{
if(stats.isFile())
{
if(path.extname(url+file) === ext)
{
var result = JSON.parse(fs.readFileSync(url+file));
getWordAndOutput(result,null);
}
}else if(stats.isDirectory())
{
getFiles(url+file+'/', ext);
}
})
})
})
}
getFiles('../FontDome/resource/config/', '.json');
getTxt.js脚本中getFiles是放项目中的json文字的目录
minFont.js如下
var fs = require("fs")
var Fontmin = require('fontmin');
var t = fs.readFileSync("nodeJs/output.txt", "utf8");
var srcPath = 'bigfonts/*.ttf';
var destPath = '../FontDome/resource/assets/fonts/';
fs.readdir('bigfonts', function(err, files){
if(err){
console.log('error:\n' + err);
return;
}
files.forEach(function(file){
fs.stat('bigfonts' + '/' + file, function(err, stat){
if(err){console.log(err); return;}
if(stat.isDirectory()){
//文件夹遍历
explorer('bigfonts' + '/' + file);
}else{
// 读出所有的文件
if(file.slice(-4) != "tore"){
var fontmin = new Fontmin()
.src('bigfonts' + '/' + file)
.use(Fontmin.glyph({
text:t
}))
//.use(Fontmin.ttf2eot())
.use(Fontmin.ttf2woff())
//.use(Fontmin.ttf2svg())
.use(Fontmin.css(
{
fontFamily: function (font, ttf) {
console.log('文件名:' + 'bigfonts' + '/' + file.slice(0,file.length-4));
return ttf.name.fontFamily =file.slice(0,file.length-4);
}
}))
.dest(destPath);
fontmin.run(function (err, files, stream) {
if (err) {
console.error(err);
}
console.log('done');
});
}
}
});
});
});
minFont.js中destPath是压缩后存放字体的目录地址
fonts.sh执行脚本如下:
#!/bin/bash
DIR="$( cd "$( dirname "$0" )" && pwd )"
cd $DIR
node nodeJs/getTxt.js
node nodeJs/minFont.js
对压缩后的字体选择:ttf以及woff
原因如下:
1.TTF字体:
支持的浏览器:IE9+,Firefox3.5+,Chrome4+,Safari3+,Opera10+,iOS Mobile Safari4.2+
2.WOFF字体:
支持的浏览器:IE9+,Firefox3.5+,Chrome6+,Safari3.6+,Opera11.1+
这两种字体可以覆盖大部分运行环境
因为h5,app,微信的导入字体方式不同,因此将三种方式都进行了统一简单封装。
封装ts脚本如下:
declare namespace egret {
export function registerFontMapping(name: string, path: string): void;
}
namespace Fonts {
export var fontArray: Array<string> = [];
export var count: number = 0;
export var loadArray = ["font"];
export function getResUrl(fontTpye: string) {
return 'resource/assets/fonts/'+fontTpye+'.ttf';
}
export function getResCssUrl(name: string) {
return 'resource/assets/fonts/' + name + '.css';;
}
export function loadFont(fontTpye: string, obj: { callbackSucceed: Function, callbackFailure: Function }, callbackThisObj: any) {
if (Fonts.fontArray.indexOf(fontTpye) != -1) {
return obj.callbackSucceed.call(callbackThisObj);
}
if (App.Util.isWXgame()) {
let ulr: string = Fonts.getResUrl(fontTpye);
Fonts.count++;
loadFontWX(ulr).then(res => {
obj.callbackSucceed.call(callbackThisObj);
Fonts.fontArray.push(fontTpye);
console.log('success:', res);
}).catch(() => {
Fonts.reLoad(fontTpye, obj, callbackThisObj);
console.error('fail:', )
})
} else if (App.Util.isRuntime()) {
Fonts.loadApp(fontTpye, obj, callbackThisObj);
} else {
Fonts.loadttf(fontTpye, (num) => {
console.log(fontTpye);
Fonts.count++;
if (num != 2) {
Fonts.count = 0;
obj.callbackSucceed.call(callbackThisObj)
Fonts.fontArray.push(fontTpye);
} else {
Fonts.reLoad(fontTpye, obj, callbackThisObj);
}
});
}
}
export function reLoad(fontTpye: string, obj: { callbackSucceed: Function, callbackFailure: Function }, callbackThisObj: any) {
if (Fonts.count >= 5) {
Fonts.count = 0;
obj.callbackFailure.call(callbackThisObj)
} else {
Fonts.loadFont(fontTpye, obj, callbackThisObj);
}
}
//h5加载字体
export function loadttf(name, callback) {
if (document["fonts"]) {
var values = document["fonts"].values();
var isLoaded = false;
var item = values.next();
while (!item.done && !isLoaded) {
var fontFace = item.value;
if (fontFace.family == name) {
isLoaded = true;
}
item = values.next();
}
if (isLoaded) {
callback(1);
return;
}
}
if (window["FontFace"]) {
var font = new window["FontFace"](name,'url('+Fonts.getResUrl(name)+')' );
font.load().then(function (loadedFontFace) {
if (loadedFontFace.status == "loaded") {
document["fonts"].add(loadedFontFace);
callback(1);
} else {
callback(2);
}
});
} else {
if (window["document"]) {
dynamicLoadCss(name);
callback(3);
} else {
callback(2);
}
}
}
async function dynamicLoadCss(name) {
var head = document.getElementsByTagName('head')[0];
var link = document.createElement('link');
link.type = 'text/css';
link.rel = 'stylesheet';
link.href = Fonts.getResCssUrl(name);
head.appendChild(link);
console.log("开始加载css");
}
//app加载字体
export function loadApp(name: string, obj: { callbackSucceed: Function, callbackFailure: Function }, callbackThisObj: any) {
if (RES.hasRes(name+"_ttf")) {
loadArray.push(name+"_ttf");
}
console.log("开始加载loadApp");
// app字体加载与资源加载方式一样,以下为自己封装的加载方式,你可使用自己的资源加载方式,关于资源加载方式以后会专门写一篇
// let ResMgr;
// let groupName: string = ResMgr.loadResources(loadArray, [], () => {
// console.log("加载loadApp字体成功");
// Fonts.fontArray.push(name);
// egret.registerFontMapping(name, Fonts.getResUrl(name));
// obj.callbackSucceed.call(callbackThisObj);
// }, (event: RES.ResourceEvent) => {
// }, loadApp, (e: RES.ResourceEvent) => {
// });
}
//微信加载字体
export function loadFontWX(_url: string): Promise<any> {
return new Promise((resolve, reject) => {
const fontName: string = window['wx'].loadFont(_url);
if (fontName) {
resolve(fontName);
} else {
reject();
}
})
}
}
其中
declare namespace egret {
export function registerFontMapping(name: string, path: string): void;
}
是app环境使用;
如何判断运行环境
namespace App
{
export class Util
{
//判断微信平台
public static isWXgame():boolean
{
return egret.Capabilities.runtimeType == egret.RuntimeType.WXGAME;
}
//是否是runtime微端环境
public static isRuntime():boolean
{
return egret.Capabilities.runtimeType==egret.RuntimeType.RUNTIME2;
}
//是否Html5版本
public static IsHtml5():boolean
{
return !this.isWXgame() && egret.Capabilities.runtimeType == egret.RuntimeType.WEB;
}
}
}
如何在项目中使用脚本:
字体更新至default.res.json之后。在需要使用字体的地方调Fonts.loadFont()方法
Fonts.loadFont(name,{
callbackSucceed:()=>{},
callbackFailure:()=>{}
},this);
name:字体名
callbackSucceed:加载成功返回函数
callbackFailure:加载失败返回函数
加载成功之后将 字体名 赋值给相应文字的 fontFamily 属性
注:经测试压缩比为百分之90