一 自定位图文字

因为egret的位图文字是texturemerger做的,需要多张单图片导入tm,然后导出两个文件来使用,过程比较麻烦。

而Laya的位图文字则是一张整图数字图片,使用FontClip就能直接使用, 很方便。

所以现在弄个自定义的位图文字类,也不用tm去导图了。

二 决战沙城的位图文字代码

先来看看别人的。据说这个框架里的位图文字被用于很多大型H5 mmo项目。14年写的工具类ε=(´ο`*)))唉。

主要原理就是1个字1个bitmap,然后并列排起来。“123“就是3个bitmap排起来。

/**
* 素材需要提前加载好
* 素材命名规则:类型_数值(有类型是因为一般会同时有几种数字图片,比如大小号或不同颜色)
* 点号素材命名:类型_dot
* 创建BitmapNumber使用createNumPic返回DisplayObjectContainer
* 创建好的BitmapNumber数值需要变化是调用changeNum
* 回收使用desstroyNumPic
*
* Created by Saco on 2014/8/1.
*/
class BitmapNumber extends SingtonClass {
private _imgPool:egret.Bitmap[];
private _containerPool:egret.DisplayObjectContainer[]; public constructor() {
super();
this._imgPool = [];
this._containerPool = [];
} /*
* 根据需要的数字和类型返回一个DisplayObjectContainer
* num数字值,支持小数点
* type素材类型
* */
public createNumPic(num:number, type:string):egret.DisplayObjectContainer {
var container:egret.DisplayObjectContainer = this.getContainer();
var numStr:string = num.toString();
var index:number = 0;
var tempBm:egret.Bitmap;
for (index; index < numStr.length; index++) {
tempBm = this.getSingleNumPic(numStr.charAt(index), type);
container.addChild(tempBm);
}
this.repositionNumPic(container);
return container;
} //回收带数字的DisplayObjectContainer
public desstroyNumPic(picContainer:egret.DisplayObjectContainer):void {
this.clearContainer(picContainer);
if (picContainer.parent)
picContainer.parent.removeChild(picContainer);
this._containerPool.push(picContainer);
} /*
* 改变带数字的DisplayObjectContainer数字值
* 提供这个方法是为了提高效率,直接更换之前创建对象的texture,避免多余的删除和创建
* */
public changeNum(picContainer:egret.DisplayObjectContainer, num:number, type:string):void {
var numStr:string = num.toString();
var tempBm:egret.Bitmap;
//如果当前数字个数多于目标个数则把多余的回收
if (picContainer.numChildren > numStr.length) {
while (picContainer.numChildren > numStr.length) {
this.recycleBM(<egret.Bitmap>picContainer.getChildAt(picContainer.numChildren - 1))
}
}
var index:number = 0;
var tempStr:string;
for (index; index < numStr.length; index++) {
//如果当前的Bitmap数量不够则获取新的Bitmap补齐
if (index >= picContainer.numChildren)
picContainer.addChild(this.getBitmap());
tempStr = numStr.charAt(index);
tempStr = tempStr == "." ? "dot" : tempStr;
(<egret.Bitmap>picContainer.getChildAt(index)).texture = this.getTexture(tempStr, type);
}
this.repositionNumPic(picContainer);
} //每个数字宽度不一样,所以重新排列
private repositionNumPic(container:egret.DisplayObjectContainer):void {
var index:number = 0;
var lastX:number = 0;
var temp:egret.DisplayObject;
for (index; index < container.numChildren; index++) {
temp = container.getChildAt(index);
temp.x = lastX;
lastX = temp.x + temp.width;
}
} //清理容器
private clearContainer(picContainer:egret.DisplayObjectContainer):void {
while (picContainer.numChildren) {
this.recycleBM(<egret.Bitmap>picContainer.removeChildAt(0));
}
} //回收Bitmap
private recycleBM(bm:egret.Bitmap):void {
if (bm && bm.parent) {
bm.parent.removeChild(bm);
bm.texture = null;
this._imgPool.push(bm);
}
} private getContainer():egret.DisplayObjectContainer {
if (this._containerPool.length)
return this._containerPool.shift();
return new egret.DisplayObjectContainer();
} //获得单个数字Bitmap
private getSingleNumPic(num:string, type:string):egret.Bitmap {
if (num == ".")
num = "dot";
var bm:egret.Bitmap = this.getBitmap();
bm.texture = this.getTexture(num, type);
return bm;
} private getTexture(num:string, type:string):egret.Texture {
return RES.getRes(type + num);
} private getBitmap():egret.Bitmap {
if (this._imgPool.length)
return this._imgPool.shift();
return new egret.Bitmap();
}
}

 

顺便看了下凡人修仙传的位图文字。可以看到文字是一整张合图且无序排列,而且network里没有fnt文件。推测应该也是使用支持单张数字的自定义位图文字。

三 我自己写了个

相对于决战沙城的有些改动

1. 支持使用整图和单张图片。

2. 支持代码创建和拖动到exml上摆放。

3. 文字图片可以使用tm和其他图片进行合并,减少drawcall和http请求,而不影响位图文字的使用。

需要注意的是

1. 不要用cacheAsBitmap,对于变化数字非常卡。我试了下,卡爆了。

测试用整图

测试用单张图

具体代码

/**
* 位图文字
* @deprecated 可以使用单张整图或者多张散图,制作位图文字。
* 注意"."的图片命名要改为dot,例如"1"是font_1.png,那么"."的图片命名是font_dot.png。
* @author ck 2019.11.10
*/
class BitmapFont extends eui.Component{
/**位图缓存 */
private static bmCaches:Array<egret.Bitmap> = [];
/**纹理缓存 */
private static textureCaches = {};
/**显示的文字 */
private _text:string;
/**图片名 */
private pngName:string; public constructor() {
super();
} /**
* 文字在一张图上
* @param pngName 图片名 pngName = font_test (font_test.png)
* @param txt 文字名 "0123456789.+-"
*/
public static registerByOne(pngName:string, txt:string){
let textureCache = this.getTextureCache(pngName);
if(textureCache.length > 0){
console.log("位图字体缓存已存在:",pngName);
return;
}
let src:egret.Texture = new egret.Texture();
src = RES.getRes(pngName + "_png");
let len = txt.length;
let fontWidth:number = src.textureWidth/len;
let fontHeight:number= src.textureHeight;
let texture:egret.Texture;
let rect:egret.Rectangle = new egret.Rectangle();
for(let i=0;i<len;i++){
texture = new egret.Texture();
texture.disposeBitmapData = false;
texture.$bitmapData = src.$bitmapData
texture.$initData(i*fontWidth,0, fontWidth, fontHeight, 0, 0, fontWidth, fontHeight, src.textureWidth, src.textureHeight);
textureCache[txt.charAt(i)] = texture;
}
} /**
* 文字在不同的图片上
* @param pngName 图片名 pngName=font_test 多张图片源文件名(font_test0.png font_test1.png .... font_testdot.png)
* @param txt 文字名 "0123456789.+-"
*/
public static registerByMulti(pngName:string, txt:string){
let textureCache = this.getTextureCache(pngName);
if(textureCache.length > 0){
console.log("位图字体缓存已存在:",pngName);
return;
}
let len = txt.length;
let char:string;
for(let i=0;i<len;i++){
char = txt.charAt(i);
if(char == "."){
textureCache[char] = RES.getRes(pngName + "dot" + "_png");
}else{
textureCache[char] = RES.getRes(pngName + char + "_png");
}
}
} /**
* 获取纹理缓存
* @param pngName 图片名
*/
public static getTextureCache(pngName:string){
let textureCache = BitmapFont.textureCaches[pngName];
if(textureCache == null){
textureCache = [];
BitmapFont.textureCaches[pngName] = textureCache;
}
return textureCache;
} /**
* 设置文字
* @param txt 文字
*/
public set text(txt:string){
let bmCaches = BitmapFont.bmCaches;
let textureCache = BitmapFont.getTextureCache(this.pngName);
let curLen = this.numChildren;
let targetLen = txt.length; this._text = txt; //文字存在,且大于显示文字,则移除多余文字
if(curLen > targetLen){
let bm:egret.Bitmap;
for(let i=curLen-1;i>=targetLen;i--){
bm = this.removeChildAt(i) as egret.Bitmap;
bm.texture = null;
bmCaches.push(bm);
}
}
//显示文字
let bm:egret.Bitmap;
let tempX:number = 0;
let char:string;
for(let i=0;i<targetLen;i++){
//少于显示文字,则增加文字
if(i >= curLen){
if(bmCaches.length > 0){
bm = bmCaches.pop();
}else{
bm = new egret.Bitmap();
}
this.addChild(bm);
}
bm = this.getChildAt(i) as egret.Bitmap;
bm.texture = textureCache[txt.charAt(i)];
bm.x = tempX;
tempX = bm.x + bm.width;
}
} /**
* 获取文字
*/
public get text(){
return this._text;
} /**
* 设置文字类型
* @value 字体类型 文字是font_test.png一张图片,则value = "font_test""。 若文字是font_test0.png font1_test1.png..多张图片,则value="font_test"
*/
public set font(value:string){
this.pngName = value;
} /**销毁 */
public destroy(){
//回收bitmap
let len = this.numChildren;
let bm:egret.Bitmap;
let bmCaches = BitmapFont.bmCaches;
for(let i=len-1;i>=0;i--){
bm = this.getChildAt(i) as egret.Bitmap;
this.removeChild(bm);
bm.texture = null;
bmCaches.push(bm);
}
//从视图移除
this.parent && this.parent.removeChild(this);
}
}

  

使用示例

 //注册
BitmapFont.registerByOne("font_test","02345"); //使用
let mc:BitmapFont = new BitmapFont();
mc.font = "font_test";
mc.text = "0222";
this.addChild(mc);

  

运行效果

四 测试下效率

新建n个位图文字放到列表bmList,然后不停的切换数字显示

private onEnterFrame(){
for(let i=0;i<this.bmList.length;i++){
//BitmapNumber.ins().changeNum(this.bmList[i],(Math.random()>0.5)?200000:200,"font" );
this.bmList[i].text = (Math.random()>0.5)?"200000":"200";
}
} 

200个         1000个           2000个         4000个

自定义字体           60FPS      58-60FPS        30FPS         8FPS

BtimapLabl          60FPS       59-60FPS        59-60FPS    30FPS

决战沙城              60FPS       59-60FPS        24FPS         8FPS

最新文章

  1. poj1131-Octal Fractions(进制转换)
  2. DirectX12 Samples 学习笔记 – PredicationQueries
  3. gradient 线性渐变 浏览器兼容
  4. mac os x使用技巧及常用软件
  5. 实验一 Java开发环境的熟悉-刘蔚然
  6. C#利用Windows API 实现关机、注销、重启等操作
  7. delphi Pointer 转成string
  8. Struts-2.3.24.1官方例子-struts2-blank
  9. (hdu)5652 India and China Origins 二分+dfs
  10. [Entity Framework]获取部分字段的查询
  11. WebSocket学习笔记IE,IOS,Android等设备的兼容性问
  12. MySQL慢查询(二) - pt-query-digest详解慢查询日志
  13. Walking Ant(一道有意思的蚂蚁游戏,bfs)
  14. (Android) ContentProvider 实例
  15. httping:测量网站延迟
  16. bzoj 2229: [Zjoi2011]最小割
  17. NopCommerce是什么(转自CNSD)
  18. Python socket的客户端
  19. JavaScript命名规范基础及系统注意事项
  20. cf1139D. Steps to One(dp)

热门文章

  1. Kali linux network is unreachable
  2. AWS 存储过程
  3. Dapper 一对多查询 one to many
  4. Distance(2019年牛客多校第八场D题+CDQ+树状数组)
  5. 洛谷P2216 理想的正方形(单调队列)
  6. 查看服务器被访问最大的ip
  7. Virtual DOM的渲染机制--猜测
  8. afnetwork moya 都符合通信协议七层模型
  9. Tic-Tac-Toe-(暴力模拟)
  10. [Javascript] ES6 Class Constructors and the Super Keyword