egret图文并的实现和想法
图文并排,是图片和文本并列排在一起。
在某些需求中,比如聊天,在输入某些文字的同时需要添加一些表情图片,或者动态图片使得表达更加生动。
那么在游戏引擎中,文本的渲染计算是单独的。那么图文并排应该怎么实现呢?
1.在字体中加入图片(未实现)
其实文字本身也是图片,所以如果这个字体文件中存在我们需要的图片的话,那么我们在给文本赋值是在相应的文本给出对应的图片名字
就行。
但是如果我们无法对某个字体A文件做出相应的修改,这个个字体又是我们非常需要的,一定要用的怎么办?
我们可以重新生成一个新的字体B,字体中只有对应的图片
使用egret的富文本格式来个Label.text赋值
<Array<egret.ITextElement>>[{text:“xxx是真的xxx”,style:{fontFamily:“字体A”}},{text:“图片”,style:{fontFamily:“字体B”}}];
那么这样我们就可以不需要设置图片的位置排列了!
2.不能修改字体,那么我在文本赋值的时候用特殊字符代替图片,在关键位置插入图片掩盖住特殊字符那么,看上去也能达到相应的效果。
我们也无法知道在文本渲染出来之前知道某个文字在舞台中的位置。
但是我们需要知道某个文字的位置才能计算出准确位置。
在egret 引擎中可以使用eui.Label和Group来进行再次封装。
1.准备素材:
2.保证加载
3.创建eui
4.代码
/**
* 图文混排
*/
class GraphicMixed extends eui.Component{
private contentGroup:eui.Group;
private text:eui.Label;
//字号大小
private fontSize:number;
//文本内容
private str: string;
//图片引用
private rtImageList: RichTextImage[];
//图片id保存
private imageIds:any[];
constructor(text:string=""){
super();
this.skinName = "skinTestUI";
this.str = text;
this.init();
this.setTextValue(text)
}
//初始化
private init():void{
this.fontSize = this.text.size;
this.rtImageList = [];
}
//对文本赋值
private setTextValue(content:string):void{
if(!content||content=="")
return ;
//使用正则来替换需要,假设图片id 1 - 99
let regex = /\[#[0-9]{1,99}\]/gim;
//有图片的地方需要用同字体大小的中文丶来替代,图片的大小是字体的大小
let replaceStr = `<font size="${this.fontSize}">丶</font>`;
this.imageIds = content.match(regex);
//获得替换后的文本
this.str = content.replace(regex,replaceStr);
//转成富文本
this.text.textFlow = (new egret.HtmlTextParser).parser(this.str);
//渲染文本
this.text.validateNow();
this.text.once(egret.Event.ENTER_FRAME,this.calculatePosition,this);
}
//计算位置
private calculatePosition():void{
let text = this.text;
let imgIds = this.imageIds;
let index = 0;
let y = 0;
//对文本的 linesArr (私有属性)进行访问,以计算出需要显示的图片的位置并设置
text['linesArr'].forEach((item, lines) => {
let x = text.x;
y += item.height;
for (let i = 0; i < item.elements.length; i++) {
let element: egret.IWTextElement = item.elements[i]
x += element.width;
if (element.text == '丶') {
let idStr = imgIds[index++].match(/[0-9]+/);
this.rtImageList.push(new RichTextImage(text.parent,idStr[0], x - this.fontSize, y- this.fontSize, this.fontSize));
}
}
})
}
public Test()
{
this.str = ""
this.str += "<font color=0xB600FF >669900今天天气不错669900669900今天天气不错669900</font>[#1]";
this.str += "\n[#2]";
this.str += "[#3]";
this.str += "[#4]";
this.str += "669900今天天气不错669900669900今天天气不错669900[#5]";
this.str += "[#6]";
this.str += "[#7]";
this.str += "669900今天天气不错669900669900今天天气不错669900[#10]";
this.str += "669900今天天气不错669900669900今天天气不错借鸡生蛋卡德加[#11] [#12] [#13][#14] [#15]";
this.setTextValue(this.str)
}
}
class RichTextImage {
id:string
x: number
y: number
source: string
size: number
parent: egret.DisplayObjectContainer
constructor(parent: egret.DisplayObjectContainer, imgId: string, x: number, y: number, size: number) {
this.id = imgId
this.x = x;
this.y = y
this.source = `icon0${this.id}_png`
this.size = size
this.parent = parent
this.LoadImage()
console.error(this.id)
}
public LoadImage() {
//获取表情
var bitmap: egret.Bitmap = new egret.Bitmap(RES.getRes(this.source));
bitmap.width = this.size
bitmap.height = this.size
bitmap.x = this.x
bitmap.y = this.y
this.parent.addChild(bitmap);
}
/**播放序列帧动画 */
playFrameAnimation() {
}
}
在Main.ts上添加到舞台
5.运行结果