导入外部字体且带字体压缩,以及判断h5,app,微信小游戏环境和字体的具体实现方式(egret为例)

1.压缩字体方式

因为一般项目中不需要用到所有字体,所以需要将需要的字体在字体包提取出来重新打字体包
我选择的压缩字体方式是 :使用fontmin进行字体压缩
fontmin官网为: https://blog.ipsfan.com/4298.html 可自行查看介绍以及相关api

为了以后操作方便,所以准备将压缩字体做成脚本化方式

首先确定一下目录结构,如下图
导入外部字体且带字体压缩,以及判断h5,app,微信小游戏环境和字体的具体实现方式(egret为例)_第1张图片
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个文件,如下图:
导入外部字体且带字体压缩,以及判断h5,app,微信小游戏环境和字体的具体实现方式(egret为例)_第2张图片
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+
这两种字体可以覆盖大部分运行环境

2.将字体导入项目中(egret为例)

因为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

你可能感兴趣的:(egret,cocos,creator,layabox,typescript,javascript,html5)