Egret自定义位图文字(自定义+BitmapLabel)
一 自定位图文字
因为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
Egret自定义位图文字(自定义+BitmapLabel)的更多相关文章
- Android实现自定义带文字和图片的Button
Android实现自定义带文字和图片的Button 在Android开发中经常会需要用到带文字和图片的button,下面来讲解一下常用的实现办法. 一.用系统自带的Button实现 最简单的一种办法就 ...
- WPF自定义空心文字
首先创建一个自定义控件,继承自FrameworkElement,“Generic.xaml”中可以不添加样式. 要自定义空心文字,要用到绘制格式化文本FormattedText类.FormattedT ...
- Android之自定义画图文字动画
结构: BaseView: package com.caiduping.canvas; import android.content.Context; import android.graphics. ...
- oracle的order by decode根据文字自定义排序的例子
oracle的order by decode根据文字自定义排序的例子: order by decode(t.title, '当前生效预警', 1, '今日即将生效', 2, '明日预计生效', 3, ...
- 写了一个迷你toast提示插件,支持自定义提示文字和显示时间
写了一个迷你toast提示插件,支持自定义提示文字和显示时间,不想用其他第三方的ui插件,又想要toast等小效果来完善交互的同学可以试试, 代码中还贡献了一段css能力检测js工具函数,做项目的时候 ...
- Laya的位图文字
参考: Laya文本 测试版本:Laya 2.1.1.1 大部分游戏都会用到位图文字,例如dnf的伤害数字. 白鹭的位图文字是美术提供0-9十张单张图片,由TextureMerger导出fnt+jso ...
- Dialog详解(包括进度条、PopupWindow、自定义view、自定义样式的对话框)
Dialog详解(包括进度条.PopupWindow.自定义view.自定义样式的对话框) Android中提供了多种对话框,在实际应用中我们可能会需要修改这些已有的对话框.本实例就是从实际出发, ...
- asp.net MVC 自定义@helper 和自定义函数@functions小结
asp.net Razor 视图具有.cshtml后缀,可以轻松的实现c#代码和html标签的切换,大大提升了我们的开发效率.但是Razor语法还是有一些棉花糖值得我们了解一下,可以更加强劲的提升我们 ...
- activiti自定义流程之自定义表单(三):表单列表及预览和删除
注:(1)环境配置:activiti自定义流程之自定义表单(一):环境配置 (2)创建表单:activiti自定义流程之自定义表单(二):创建表单 自定义表单创建成功,要拿到activiti中使用,自 ...
随机推荐
- ssm上传文件
ssm上传文件(上传到本地磁盘) (1)先要导入所需要的jar包或者pom文件中添加依赖 <!-- 上传 --> <dependency> <groupId>com ...
- 函数中,对形参做不加var的全局溢出赋值,可改变形参所指向的实参的本身值
var formateNumArr = function(arr,defaultVal){ var a = []; $.each(arr,function(i,v){ ...
- 基于TCP和UDP的Socket通信
TCP的Socket通信 TCP是面向连接的,安全的协议,它是一对一的关系 server client 上面只是单个客户端同服务器通信,可使用多线程编程实现多个客户端的通信 UDP的Socket通信 ...
- 学习:多字节编码(ANSI)和UNICODE编码的关系
Windows 既可以使用 Unicode 字符集又可以使用传统的字符集(如多字节编码)来实现对多种语言的支持,以适应国际市场的要求.与传统的字符集编码相比,Unicode 是世界通用的字符编码标准, ...
- XXE(外部实体注入攻击)
利用XXE漏洞可以进行拒绝服务攻击.文件读取.命令代码执行.SQL(XSS)注入.内外扫描端口和入侵内网站点等,内网探测和入侵是利用XXE中支持的协议进行内网主机和端口的发现,可以理解为使用XXE进行 ...
- 压缩、解压命令——gzip、gunzip、tar、zip、bzip2
1.gzip命令与gunzip命令(压缩解压文件): (1)gzip——压缩: 利用touch命令创建一个文件,并向里面写入内容: 对创建的文件进行压缩: (2)解压缩gzip -d或gunzip: ...
- 求等差数列前$n$项和$S_n$的最值
一.方法依据: 已知数列\(\{a_n\}\)是等差数列,首项为\(a_1\),公差为\(d\),前\(n\)项和为\(S_n\),则求\(S_n\)的最值常用方法有两种: (1).函数法:由于\(S ...
- jQuery动画和遍历
一.动画 1. 动画 1. 三种方式显示和隐藏元素 1. 默认显示和隐藏方式 1. show([speed,[easing],[fn]]) 1. 参数: 1. speed:动画的速度.三个预定义的值( ...
- Pytest权威教程19-编写钩子(Hooks)方法函数
目录 编写钩子(Hooks)函数 钩子函数验证和执行 firstresult: 遇到第一个有效(非None)结果返回 hookwrapper:在其他钩子函数周围执行 钩子(Hooks)函数排序/调用示 ...
- JavaScript base64 加密解密
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...