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中使用,自 ...
随机推荐
- Kali -关闭防火墙
kali关闭防火墙前需要安装ufw 安装 apt-get install ufw 关闭 ufw disable # To disable the firewall 开启 ufw enable # To ...
- zabbix--邮件告警
zabbix 邮件告警机制 通过腾讯企业邮箱进行告警通知等.邮箱服务器账号需要在邮箱设置里面进行设置,开通ssl认证及专用密码 参考官档:https://www.zabbix.com/document ...
- Dart 知识点:位置参数(必选)、位置参数(可选)、命名参数(都是可选)
先后顺序:位置参数(必选).位置参数(可选).命名参数(都是可选) 位置参数(可选).命名参数(都是可选),不能同时使用
- js不常用,但很实用的功能
=============== 通知: 博主已迁至<掘金>码字,博客园可能以后不再更新,掘金地址:https://juejin.im/post/5a1a6a6551882534af25a8 ...
- python + redis +ipset实现IP黑名单的动态添加及解封禁
1.抽空用python做了一个 动态添加/删除IP黑名单 的程序(或者说实现方案),项目地址: https://gitee.com/lowmanisbusy/ip_blacklists, 2.这里的实 ...
- Linux—— 报错汇总
前言 记录Linux相关的错误问题和解决方法 问题 tar: Error is not recoverable: exiting now [报错] tar -zxvf mysql-server_5.6 ...
- 【Redis】远程访问不了
Windows安装后,启动的服务配置文件是redis.windows-service.conf "D:\Program Files\Redis\redis-server.exe" ...
- 强制结束虚拟机 centos home 卷丢失导致无法挂载进入 emergency mode 紧急模式
参考文章: https://blog.51cto.com/13059784/2054378 xfs文件修复参考1:https://codeday.me/bug/20181112/367781.html ...
- MATLAB画图笔记
plot函数 plot(x,y)默认格式: 若x,y是向量,则它们必须具有相同的长度.函数将以x为横轴,绘制y. 若x,y都是矩阵,则它们必须具有相同的尺寸,plot函数将针对x的各列绘制y的每列.更 ...
- 7-zip命令行详解
一.简介 7z,全称7-Zip, 是一款开源软件.是目前公认的压缩比例最大的压缩解压软件. 主要特征: # 全新的LZMA算法加大了7z格式的压缩比 # 支持格式: * 压缩 / 解压缩:7z, XZ ...