当前位置: 首页 > news >正文

Cocos Creator 之 Label的实际宽高改变文本背景大小及常用方法

引擎: 3.8.5

环境: Mac

您好,我是鹤九日!



简介


有些情况下,我们需要根据文本的宽、高动态设置文本背景的大小。

这里汇总了几种一些案例,以及一些文本转换的常用方法,希望对您有用。



案例1:Layout模式


Layout是Cocos提供的布局容器,如果根据Label的宽、高动态设置文本背景的大小,我们可以这样做:

一、添加一个图片节点,挂载Layout组件,组件属性可为水平或垂直,缩放模式必须为Container。

二、图片节点下添加文本节点,这里注意:

  1. 如果Layout组件为水平,则文本无特殊设置

  2. 如果Layout组件为垂直,则文本的溢出为RESIZE_HEIGHT

三、注意设置图片和文本节点的锚点,此实例中均为(0,1)。

Layout配置相关:

请添加图片描述

Label配置相关:

请添加图片描述

如上,通过编译器的属性检查器,就可直观的查看效果,不需编写脚本代码。



案例2: 代码的动态配置


上面的例子虽然直观,但可能有着这样的问题:

一、水平模式下会无限拉伸,可能不满足需求

二、垂直模式下倘若无内容,因为文本Resize_Height的设定,宽度固定,会显示一个默认背景。

请添加图片描述

三、Layout刷新和文本的实际宽高导致其他不必要的问题。

结合可能出现的问题,这里不再借助Layout,而是使用引擎提供的一些API接口实现效果。编译器配置如下:

一、 添加图片父节点、文本子节点,各自锚点均为(0,1) 文本对齐为左上。

二、文本子节点添加Widget组件,AlignMode为Always,用于节点发生改变时重新对齐。

请添加图片描述

代码逻辑如下:

const desc = "这是一段文本内容这是一段文本内容";
const label = this.labelNode.getComponent(Label);
label.string = desc;// 立即更新渲染数据,用于获取文本的实际宽高
label.updateRenderData(true);// 检测文本宽度是否超过限定宽度,倘若超过则设置溢出模式
const labelWidth = this.labelNode.getComponent(UITransform).width;
if (labelWidth > 450) {label.overflow = Overflow.RESIZE_HEIGHT;this.labelNode.getComponent(UITransform).width = 450;label.updateRenderData(true);
}// 根据文本的宽高设置修改背景宽高
const labelSize = this.labelNode.getComponent(UITransform).contentSize;
const bgTransform = this.bgNode.getComponent(UITransform);
bgTransform.setContentSize(labelSize.width, labelSize.height);

原理:设置文本内容后,获取文本的实际宽高,然后根据文本高宽设置背景大小。

注释较为详细,这里不再赘述了,主要接口是:updateRenderData



延伸


案例2的模式,是可用于聊天的内容拓展的。

只不过聊天的内容是展示在列表中,每一条内容的展示都是Item预制体。

这样的话,Item的宽高我们依然需要做动态修改。大致实现原理是这样的:

一、 设置文本内容,并强制刷新获取实际的宽高

二、根据文本的宽高,动态设置背景大小

三、根据背景的大小,动态设置Item的大小。

这便是聊天的自适配,大致的逻辑代码:

// 设置文本内容,并强制刷新
const contentLabel = contentNode.getComponent(Label);
contentLabel.string = info.message;
contentLabel.updateRenderData();// 检测如果文本宽度大于限定宽度,则将文本排版格式修改为自动更新高度的属性,并强制刷新
let labelWidth = contentNode.getComponent(UITransform).width;
if (labelWidth > 400) {contentLabel.overflow = Overflow.RESIZE_HEIGHT;contentNode.getComponent(UITransform).width = maxWidth;contentLabel.updateRenderData();
}// 根据文本宽度修改背景宽、高
const textSize = contentNode.getComponent(UITransform).contentSize;
bgNode.getComponent(UITransform).setContentSize(textSize.width + 50, textSize.height + 10);
// 根据背景的高度修改Item高度
const itemHeight = bgNode.getComponent(UITransform).height;
this.node.getComponent(UITransform).height = itemHeight + 40;

注:示例效果就不粘贴了!



案例3: 图标固定,动态修改文本背景


项目开发中,可能也会遇到这样的情况,比如:

请添加图片描述

根据数字的大小,动态拉伸背景,切保持图标一直靠右对齐。

这种方式,实际同案例2是相似的,核心点在于使用Widget组件,且AlignMode模式必须为:ALWAYS

注:文本节点、图标节点均要添加Widget组件,只不过:
文本对齐为居中,图标为右对齐

请添加图片描述

大致代码如下:

this.coinLabel.string = "100000000000";
this.coinLabel.updateRenderData(true);// 134为原有的文本宽度
const limitWidth = 134;         
const labelTransform = this.coinLabel.node.getComponent(UITransform);
if (labelTransform.width > limitWidth) {// 获取增加的宽度let addWidth = labelTransform.width - limitWidth;// 根据增加的宽度,拉伸背景(300为原有的背景宽度)const bgTransform = this.coinBgNode.getComponent(UITransform);//bgTransform.width = bgTransform.width + addWidth;bgTransform.width = 300 + addWidth;
}

效果:

请添加图片描述

注:注释掉的代码也能满足效果实现,为什么会使用固定数字呢?

原因在于:如果您频繁的刷新数字的显示,背景会随着addWidth的改变而无限拉伸的。



延伸:内容的特殊展示

文本内容中有些数字需要做特殊的展示,这里从oops-framework框架中摘录一些常用的接口。

感兴趣的小伙伴可以自行下载: oops-framework

注:oops-framework 董刚哥开发的针对于cocosCreator的免费开源客户端框架,以插件形式存在,框架与Creator 3.x保持同步更新,使用稳定可靠,推荐!

主要的接口有:

  • 将数字转换为美式计数字符串
// 转美式计数字符串, 123456789 = 123,456,789
static numberTotPermil(value: number): string {return value.toLocaleString();
}
  • 将数字转英文单位计数
/*** 转英文单位计数* @param value 数字* @param fixed 保留小数位数* @example* 12345 = 12.35K*/
static numberToThousand(value: number, fixed: number = 2): string {const k = 1000;const sizes = ['', 'K', 'M', 'G'];if (value < k) {return value.toString();}else {const i = Math.floor(Math.log(value) / Math.log(k));const r = ((value / Math.pow(k, i)));return r.toFixed(fixed) + sizes[i];}
}
  • 将数字转中文单位计数
/*** 转中文单位计数* @param value 数字* @param fixed 保留小数位数* @example* 12345 = 1.23万*/
static numberToTenThousand(value: number, fixed: number = 2): string {const k = 10000;const sizes = ['', '万', '亿', '万亿'];if (value < k) {return value.toString();}else {const i = Math.floor(Math.log(value) / Math.log(k));return ((value / Math.pow(k, i))).toFixed(fixed) + sizes[i];}
}
  • 计算字符串长度
// 计算字符串长度,中文算两个字节
static stringLen(str: string) {let realLength = 0, len = str.length, charCode = -1;for (let i = 0; i < len; i++) {charCode = str.charCodeAt(i);if (charCode >= 0 && charCode <= 128)realLength += 1;elserealLength += 2;}return realLength;
}
  • 参数替换
/*** var str:string = "here is some info '{0}' and {1}";* StringUtil.substitute(str, 15.4, true);** "here is some info '15.4' and true"*/
public static substitute(str: string, ...rest: any[]): string {if (str == null) return '';let len: number = rest.length;let args: any[];if (len == 1 && rest[0] instanceof Array) {args = rest[0];len = args.length;}else {args = rest;}for (let i: number = 0; i < len; i++) {str = str.replace(new RegExp("\\{" + i + "\\}", "g"), args[i]);}return str;
}

大概罗列这些吧,代码来自oops-framework的StringUtil工具类,这里再次表示对作者的感谢!



最后


文章到这里就结束了,可能理解有误,期待您的指出!

如果觉得文章不错,期待您的点赞和留言,感谢!

我是鹤九日,祝您生活愉快!

http://www.xdnf.cn/news/651583.html

相关文章:

  • 【Volumetric Heatmap热力图插件的使用】
  • SpringBoot性能优化的12招
  • Flutter Container组件、Text组件详解
  • 商城图片性能优化实战:懒加载与下一代格式的化学反应
  • 游戏行业DDoS防护:基于IP信誉库的实时拦截方案
  • ArrayBlockingQueue 和 LinkedBlockingQueue 有什么区别?
  • 第一章第2节:安全生命周期(识别→防护→检测→响应→恢复)
  • LitCTF2025 WEB
  • linux文件权限管理
  • 《软件工程》-第 1 章 软件与软件工程
  • Python 网络编程入门
  • 【人工智能-agent】--使用python调用dify工作流
  • Win10/Win11终极C盘清理指南
  • 深入剖析Java中的伪共享:原理、检测与解决方案
  • RT-Thread源码阅读(3)——内核对象管理
  • ES6基础
  • 考研408《计算机组成原理》复习笔记,第二章(3)数值数据的运算(浮点数计算篇)
  • 新一代WebP2P视频物联技术:EasyRTC嵌入式音视频通信SDK助力音视频实时通信场景应用
  • 基于SpringBoot+RabbitMQ完成应用通信
  • 编程日志5.19
  • 一根网线可以有两个ip地址吗?怎么实现
  • 洛谷-P1957 口算练习题
  • 基于大模型的胃肠道功能紊乱手术全程预测与干预方案研究
  • Elasticsearch 分片驱逐(Shard Exclusion)方式简析:`_name`、`_ip`、`_host`
  • 图论 判断是否有环
  • (自用)Java学习-5.13(Redis,OSS)
  • 第三十七天打卡
  • 【EdgeYOLO】《EdgeYOLO: An Edge-Real-Time Object Detector》
  • 分布式爬虫架构设计
  • Python 实现简单OCR文本识别