SamsaraGame/assets/Script/common/CustomRichText.js
2025-04-24 17:03:28 +08:00

497 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import GameModel from "../ts/core/GameModel";
cc.Class({
extends: cc.Component,
properties: {
_type: 0,//0 聊天框 1遊戲右下角ui
type: {
get() {
return this._type;
},
set(t) {
this._type = t;
}
},
_string: '',
string: {
get() {
return this._string;
},
set(t) {
this._string = t;
this.showTextInfo();
}
},
_maxWidth: 0,
maxWidth: {
get() {
return this._maxWidth;
},
set(t) {
this._maxWidth = t;
if (t <= 0) {
this._maxWidth = 100;
}
this.node.width = t;
}
},
_fontSize: 20,
fontSize: {
get() {
return this._fontSize;
},
set(t) {
this._fontSize = t;
}
},
_lineHeight: 22,
lineHeight: {
get() {
return this._lineHeight;
},
set(t) {
this._lineHeight = t;
this.node.height = t;
}
},
_strColor: cc.Color.BLACK,
strColor: {
get() {
return this._strColor;
},
set(c) {
this._strColor = c;
this.node.color = c;
}
},
startX: 0,
startY: 0,
emojiAtlas: cc.SpriteAtlas,
joinTeamBg: cc.SpriteFrame,
item_detail: cc.Prefab,
fontRes: cc.Font
},
onLoad() {
this.node.setAnchorPoint(cc.v2(0, 1));
this.isLoad = true;
},
/**
* showLabInfo creator編輯是顯示用程序裡用不到
*/
showLabInfo() {
this.node.destroyAllChildren();
let lnode = new cc.Node();
lnode.parent = this.node;
lnode.width = this.maxWidth;
lnode.color = cc.Color.BLACK;
let lab = lnode.addComponent(cc.Label);
lab.fontSize = this.fontSize;
lab.lineHeight = this.lineHeight;
lab.string = this.string;
lab.horizontalAlign = cc.Label.HorizontalAlign.LEFT;
lab.verticalAlign = cc.Label.VerticalAlign.TOP;
lab.overflow = cc.Label.Overflow.RESIZE_HEIGHT;
lnode.setPosition(cc.v2(this.startX, this.startY));
lnode.setAnchorPoint(cc.v2(0, 1));
},
showTextInfo() {
if (this.isLoad == null) {
this.showLabInfo();
return;
}
this.node.destroyAllChildren();
this.startX = 0;
this.startY = 0;
if (this.type == 1) {
this.addScaleNode();
this.addNameNode();
}
let textInfo = [];
let msgstr = this.string;
// let patt = /\[(?:[0-9]{1,3}|1000)\]/;
// let pos = msgstr.search(patt);
// while (pos != -1) {
// if (pos > 0) {
// textInfo.push({ type: 'txt', data: msgstr.substring(0, pos) });
// }
// let numend = msgstr.indexOf(']', pos);
// let numstr = msgstr.substring(pos + 1, numend);
// textInfo.push({ type: 'img', data: numstr });
// msgstr = msgstr.substr(numend + 1);
// pos = msgstr.search(patt);
// }
// if (msgstr.length > 0) {
// textInfo.push({ type: 'txt', data: msgstr });
// }
let patt = /\[[\s\S]*?\]/;
// let patt = /\[(?:[0-9]{1,3}|1000)\]/;
let pos = msgstr.search(patt);
while (pos != -1) {
if (pos > 0) {
textInfo.push({ type: 'txt', data: msgstr.substring(0, pos) });
}
let numend = msgstr.indexOf(']', pos);
let numstr = msgstr.substring(pos + 1, numend);
let ppatt1 = /\[(?:[0-9]{1,3}|1000)\]/;
let pnumstr = '[' + numstr + ']';
let ppos1 = pnumstr.search(ppatt1);
if (ppos1 >= 0) {
textInfo.push({ type: 'img', data: numstr });
} else {
textInfo.push({ type: 'link', data: numstr });
}
// textInfo.push({ type: 'img', data: numstr });
msgstr = msgstr.substr(numend + 1);
pos = msgstr.search(patt);
}
if (msgstr.length > 0) {
if (!this.checkColor(textInfo, msgstr))
textInfo.push({ type: 'txt', data: msgstr });
}
for (const info of textInfo) {
if (info.type == 'txt') {
let str = info.data;
let cutPos = this.cutStringByWidth(str, this.maxWidth - this.startX);
while (cutPos != str.length) {
if (cutPos == 0) {
this.startX = 0;
this.startY -= this.lineHeight;
} else {
this.addLabelNode(str.substr(0, cutPos), info.color);
str = str.substr(cutPos);
}
cutPos = this.cutStringByWidth(str, this.maxWidth - this.startX);
}
if (str.length > 0) {
this.addLabelNode(str, info.color);
}
}
if (info.type == 'img') {
this.addImgNode(info.data);
}
if (info.type == 'link') {
this.addLinkNode(info.data);
}
}
if (this.startY < 0) {
this.node.width = this.maxWidth;
}
else {
this.node.width = this.startX;
}
this.node.height = -(this.startY - this.lineHeight) + 5;
},
checkColor(list, str) {
var hasColor = /\<color=#(?:[0-9]|[a-f]){6}[ ]\>.*?\<\/c(olor)?[ ]\>/g;
var arr = str.match(hasColor)
if (arr == null) return false
for (let i in arr) {
var color = arr[i].match(/#(?:[0-9]|[a-f]){6}/)[0]
var t = arr[i].replace(/\<color=#(?:[0-9]|[a-f]){6}[ ]\>/, "");
t = t.replace(/\<\/c(olor)?[ ]\>/, "");
list.push({ type: "txt", data: t, color: color })
}
return true
},
addNameNode() {
if (this.rolename == null || this.rolename == '') {
return;
}
if (this.startX > this.maxWidth - this.fontSize) {
this.startX = 0;
this.startY -= this.lineHeight;
}
let lnode = new cc.Node();
lnode.color = new cc.Color(24, 218, 224);
let title = `[${this.rolename}]`;
if (this.vipLevel > 0) {
title = `V${this.vipLevel}${title}`;
}
let textRT = lnode.addComponent(cc.Label);
// if (this.fontRes)
// textRT.font = this.fontRes;
// else
// textRT.font = GameModel.fontRes;
textRT.cacheMode = cc.Label.CacheMode.BITMAP
textRT.fontSize = this.fontSize;
textRT.lineHeight = this.lineHeight;
textRT.string = title;
lnode.setPosition(cc.v2(this.startX, this.startY));
lnode.setAnchorPoint(cc.v2(0, 1));
lnode.parent = this.node;
this.startX += lnode.width;
},
addLabelNode(str, color) {
let labelColor = this.node.color;
if (color) {
var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color)
if (result)
labelColor = cc.color(parseInt(result[1], 16), parseInt(result[2], 16), parseInt(result[3], 16));
} else {
if (this.type == 1) {
if (this.scale == 0) {
labelColor = cc.color(22, 196, 88);
} else if (this.scale == 1) {
labelColor = cc.color(0, 194, 141);
} else if (this.scale == 2) {
labelColor = cc.color(54, 171, 253);
} else if (this.scale == 3) {
labelColor = cc.color(255, 90, 90);
}
}
}
if (this.startX > this.maxWidth - this.fontSize) {
this.startX = 0;
this.startY -= this.lineHeight;
}
let lnode = new cc.Node();
lnode.color = labelColor;
let lab = lnode.addComponent(cc.Label);
// if (this.fontRes)
// lab.font = this.fontRes;
// else
// lab.font = GameModel.fontRes;
lab.cacheMode = cc.Label.CacheMode.BITMAP
lab.fontSize = this.fontSize;
lab.lineHeight = this.lineHeight;
lab.string = str;
lnode.setAnchorPoint(cc.v2(0, 1));
lnode.setPosition(cc.v2(this.startX, this.startY));
lnode.parent = this.node;
this.startX += lnode.width;
},
addScaleNode() {
if (this.scale == null) {
return;
}
let scaleFrame = null;
if (this.scale == 0) {
scaleFrame = this.emojiAtlas.getSpriteFrame('font_back_all');
}
else if (this.scale == 1) {
scaleFrame = this.emojiAtlas.getSpriteFrame('font_back_team');
}
else if (this.scale == 2) {
scaleFrame = this.emojiAtlas.getSpriteFrame('font_back_bang');
}
else if (this.scale == 3) {
scaleFrame = this.emojiAtlas.getSpriteFrame('font_back_system');
}
// else if (this.scale == 7) {
// scaleFrame = this.emojiAtlas.getSpriteFrame('font_back_system');
// }
if (scaleFrame == null) {
return;
}
if (this.startX > this.maxWidth - this.fontSize) {
this.startX = 0;
this.startY -= this.lineHeight;
}
let snode = new cc.Node();
let sp = snode.addComponent(cc.Sprite);
sp.spriteFrame = scaleFrame;
snode.setAnchorPoint(cc.v2(0, 0.5));
snode.setPosition(cc.v2(this.startX, this.startY - this.lineHeight / 2));
snode.setScale(this.lineHeight / snode.height);
snode.parent = this.node;
this.startX += snode.width * snode.scaleX;
},
addImgNode(img) {
let emojiFrame = this.emojiAtlas.getSpriteFrame(('000' + img).substr(-3) + '0000');
if (emojiFrame == null) {
return;
}
let emojiFrames = [];
for (let i = 0; ; i++) {
let frame = this.emojiAtlas.getSpriteFrame(('000' + img).substr(-3) + ('0000' + i).substr(-4));
if (frame) emojiFrames.push(frame);
else break;
}
let snode = new cc.Node();
let sp = snode.addComponent(cc.Sprite);
sp.spriteFrame = emojiFrame;
snode.setAnchorPoint(cc.v2(0, 0.5));
snode.setScale(this.lineHeight / snode.height);
snode.parent = this.node;
if (this.startX + snode.width * snode.scaleX > this.maxWidth - this.fontSize) {
this.startX = 0;
this.startY -= this.lineHeight;
}
snode.setPosition(cc.v2(this.startX, this.startY - this.lineHeight / 2));
this.startX += snode.width * snode.scaleX;
if (emojiFrames.length > 0) {
let emojiClip = cc.AnimationClip.createWithSpriteFrames(emojiFrames, 10);
emojiClip.name = 'run';
emojiClip.wrapMode = cc.WrapMode.Loop;
let nodeAni = snode.addComponent(cc.Animation);
nodeAni.addClip(emojiClip);
nodeAni.play('run');
}
},
addLinkNode(link) {
let strs = link.split("@");
if (strs.length < 2) {
this.addLabelNode(link);
return;
}
if (strs[2] == 10) {
// 加入隊伍按鈕
this.addJoinTeamNode(link)
return
}
let labelColor = this.node.color;
labelColor = cc.color(0, 194, 141);
if (this.startX > this.maxWidth - this.fontSize) {
this.startX = 0;
this.startY -= this.lineHeight;
}
let lnode = new cc.Node();
lnode.color = labelColor;
let lab = lnode.addComponent(cc.Label);
// if (this.fontRes)
// lab.font = this.fontRes;
// else
// lab.font = GameModel.fontRes;
lab.cacheMode = cc.Label.CacheMode.BITMAP
lab.fontSize = this.fontSize;
lab.lineHeight = this.lineHeight;
lab.string = '[' + strs[0] + ']';
lnode.setAnchorPoint(cc.v2(0, 1));
lnode.setPosition(cc.v2(this.startX, this.startY));
lnode.parent = this.node;
let btn = lnode.addComponent(cc.Button);
btn.transition = cc.Button.Transition.NONE;
var clickEventHandler = new cc.Component.EventHandler();
clickEventHandler.target = this.node;
clickEventHandler.component = "CustomRichText";
clickEventHandler.handler = "onLinkPropClicked";
clickEventHandler.customEventData = link;
btn.clickEvents.push(clickEventHandler);
this.startX += lnode.width;
},
/**
* 加入隊伍
* @param {*} link
*/
addJoinTeamNode(link) {
if (this.startX > this.maxWidth - this.fontSize) {
this.startX = 0;
this.startY -= this.lineHeight;
}
let snode = new cc.Node();
let sp = snode.addComponent(cc.Sprite);
sp.spriteFrame = this.joinTeamBg;
snode.setAnchorPoint(cc.v2(0, 0.5));
snode.setPosition(cc.v2(this.startX, this.startY - this.lineHeight / 2));
snode.setScale(this.lineHeight / 40);
snode.parent = this.node;
let lnode = new cc.Node();
lnode.color = new cc.Color(100, 60, 60);
let title = "加入";
let textRT = lnode.addComponent(cc.Label);
// if (this.fontRes)
// textRT.font = this.fontRes;
// else
// textRT.font = GameModel.fontRes;
textRT.fontSize = this.fontSize + 6;
textRT.lineHeight = this.lineHeight;
textRT.string = title;
lnode.setPosition(cc.v2(43, 0));
lnode.setAnchorPoint(cc.v2(0.5, 0.5));
lnode.parent = snode;
this.startX += 86 * snode.scaleX;
let btn = snode.addComponent(cc.Button);
btn.transition = cc.Button.Transition.NONE;
var clickEventHandler = new cc.Component.EventHandler();
clickEventHandler.target = this.node;
clickEventHandler.component = "CustomRichText";
if (this.type != 1)
clickEventHandler.handler = "onLinkJoinTeam";
else
clickEventHandler.handler = "onLinkPropClicked";
clickEventHandler.customEventData = link;
btn.clickEvents.push(clickEventHandler);
},
onLinkJoinTeam(event, link) {
console.log(event, link)
let strs = link.split("@");
GameModel.send('c2s_requst_team', {
roleid: GameModel.player.roleid,
teamid: strs[1]
});
},
onLinkJoinTeam1(event, link) {
let strs = link.split("@");
GameModel.send('c2s_requst_team', {
roleid: GameModel.player.roleid,
teamid: strs[1]
});
},
onLinkPropClicked(event, link) {
let datas = link.split("@");
if (datas[2] == 10) datas[2] = 9
GameModel.send("c2c_goods_info", { type: datas[2], id: datas[1] });
},
cutStringByWidth(str, w) {
// TODO : 修改此方法 1 使用池管理 2 取消本方法 使用 RichText
if (w < 0) {
w = 0;
}
let lnode = new cc.Node();
let lab = lnode.addComponent(cc.Label);
lab.fontSize = this.fontSize;
lab.lineHeight = this.lineHeight;
lab.string = str;
lnode.parent = this.node;
let tempLen = str.length;
if (lab.node.width > w) {
tempLen = Math.ceil((w / lab.node.width) * str.length) + 2;
if (tempLen > str.length) {
tempLen = str.length;
}
str = str.substr(0, tempLen);
lab.string = str;
lab._forceUpdateRenderData(true);
while (lab.node.width > w) {
str = str.substr(0, tempLen - 1);
tempLen -= 1;
lab.string = str;
lab._forceUpdateRenderData(true);
}
}
lnode.parent = null;
lnode.destroy();
return tempLen;
}
});