/* eslint-disable @typescript-eslint/ban-ts-comment */
const { ccclass, menu } = cc._decorator;
/**
* 自适应气泡组件
*
* 小于n字固定高度,自适应宽度
* 大于n字固定宽度,自适应高度
*/
@ccclass
@menu('自定义组件/自适应气泡组件/BubbleComponent')
export default class BubbleComponent extends cc.Component {
bg: cc.Node = nn<cc.Node>();
pop: cc.Node = nn<cc.Node>();
label: cc.Label = nn<cc.Label>();
show(data: {
str: string; //显示的文本
model: 'left' | 'right'; //气泡尾巴的所在位置
fontSize?: number; //字体大小
lineHight?: number; //行高
paddingLeft?: number; //左右边距
paddingTop?: number; //上下边距
fontCountLineMax?: number; //单行最大汉字占位数
}): void {
if (!this.bg) {
this.bg = this.node.getChildByName('bg');
this.pop = this.node.getChildByName('pop');
this.label = this.node.getChildByName('label').getComponent(cc.Label);
}
if (!this.bg || !this.pop || !this.label) {
console.error('child node is not found');
return;
}
this.bg.getComponent(cc.Sprite).type = cc.Sprite.Type.SLICED;
this.bg.getComponent(cc.Sprite).sizeMode = cc.Sprite.SizeMode.CUSTOM;
this.label.horizontalAlign = cc.Label.HorizontalAlign.LEFT;
const {
str,
fontSize = 24,
lineHight = 33,
paddingLeft = 24,
paddingTop = 10,
fontCountLineMax = 10,
} = data;
this.bg.setPosition(0, 0);
this.pop.setAnchorPoint(1, 0);
if (data.model === 'left') {
this.bg.setAnchorPoint(0, 0);
this.label.node.setAnchorPoint(0, 0);
this.pop.scaleX = -1;
this.label.node.setPosition(paddingLeft, paddingTop);
this.pop.setPosition(fontSize, -this.pop.height);
} else if (data.model === 'right') {
this.bg.setAnchorPoint(1, 0);
this.label.node.setAnchorPoint(1, 0);
this.pop.scaleX = 1;
this.label.node.setPosition(-paddingLeft, paddingTop);
this.pop.setPosition(-fontSize, -this.pop.height);
}
this.label.fontSize = fontSize;
this.label.lineHeight = lineHight;
//获取实际需要几行来显示,考虑开头结尾的标点纠正情况
const lineCount = this.calculateLabelLineCnt(str, fontSize * fontCountLineMax, fontSize);
if (lineCount === 1) {
this.label.overflow = cc.Label.Overflow.NONE;
} else {
this.label.node.width = fontSize * fontCountLineMax;
this.label.overflow = cc.Label.Overflow.RESIZE_HEIGHT;
}
this.label.string = str;
//@ts-ignore
this.label._forceUpdateRenderData(true);
const width = this.label.node.width + paddingLeft * 2;
const height = this.label.node.height + paddingTop * 2;
this.node.height = height;
this.node.width = width;
this.bg.width = width;
this.bg.height = height;
}
private calculateLabelLineCnt(content: string, labelWidth: number, fontSize: number) {
const matchMark = /[!,.:;'}\]%?>、‘“》?。,!]/;
const wordCnt = (labelWidth / fontSize) >> 0;
const sentence = content.split('\n');
let lineCnt = 0;
for (let i = 0, len = sentence.length; i < len; i++) {
const value = sentence[i];
for (let mark = 0, len = value.length; mark < len; ) {
lineCnt++;
mark += wordCnt;
matchMark.test(value[mark]) && mark--;
}
}
return lineCnt;
}
}
cocosCreator自适应气泡组件
于 2024-09-14 14:49:25 首次发布