feat(ibox): 实现信息弹窗背景自适应高度功能

1. 重构IBoxComp组件,移除旧的标题名称渲染逻辑
2. 添加动态背景节点,根据RichText内容自动调整高度
3. 优化cardbg和herobox预制体样式,调整尺寸与透明度
4. 新增通用背景预制体hbg,支持多配色快速复用
5. 重写ibox预制体结构,适配新的组件逻辑
This commit is contained in:
panFD
2026-08-07 21:51:48 +08:00
parent bcc57de312
commit 4caf20d4b2
8 changed files with 6127 additions and 2400 deletions

View File

@@ -19,7 +19,7 @@
* - SkillSet / FieldSkillSetSkillSet—— 技能/光环静态配置
* - EquipSetfindEquipByUuid—— 装备静态配置
*/
import { _decorator, Label, NodeEventType, RichText } from "cc";
import { _decorator, Node, NodeEventType, RichText, UITransform, Widget } from "cc";
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
import { CCComp } from "../../../../extensions/oops-plugin-framework/assets/module/common/CCComp";
import { SkillSet, SkillOverrides } from "../common/config/SkillSet";
@@ -57,6 +57,15 @@ export class IBoxComp extends CCComp {
@property(RichText)
massage_node: RichText = null!
/** 背景节点(高度随 RichText 内容动态调整) */
@property(Node)
bg_node: Node = null!
/** Bg 节点高度上下留白RichText 顶部间距 + 底部间距) */
private static readonly BG_PADDING_V: number = 24;
/** Bg 最小高度(防止内容过少时背景塌缩) */
private static readonly BG_MIN_HEIGHT: number = 60;
/**
* 初始化并渲染弹窗内容。
* @param args 见 IBoxInitArgs
@@ -92,23 +101,49 @@ export class IBoxComp extends CCComp {
// 装备详情模式
if (args?.equipUuid !== undefined) {
this.renderEquip(args.equipUuid);
return;
}
// 运行时技能详情模式(取第一个技能)
if (args?.skills) {
} else if (args?.skills) {
// 运行时技能详情模式(取第一个技能)
const first = Object.values(args.skills)[0];
if (first) {
this.renderSkill(first.uuid, first.lv);
return;
}
}
// 技能详情模式
if (args?.skillUuid !== undefined) {
} else if (args?.skillUuid !== undefined) {
// 技能详情模式
this.renderSkill(args.skillUuid, args.skillLv ?? 1, args.overrides);
return;
} else {
this.setRichText("暂无信息");
}
this.setHeroName("");
this.setRichText("暂无信息");
// RichText 排版需一帧完成,延迟同步 Bg 高度
this.scheduleOnce(() => this.syncBgHeight(), 0);
}
/**
* 根据 RichText 实际内容高度,动态调整 Bg 节点高度与位置。
* RichText 锚点已设为 (0.5, 1),从顶部向下生长;
* Bg 锚点 (0.5, 0.5),向上居中扩展,顶部对齐 RichText 顶。
*/
private syncBgHeight() {
if (!this.massage_node?.isValid) return;
const richUT = this.massage_node.getComponent(UITransform);
if (!richUT) return;
const contentH = Math.max(richUT.height, 0);
const bgH = Math.max(contentH + IBoxComp.BG_PADDING_V, IBoxComp.BG_MIN_HEIGHT);
const bgNode = this.bg_node ?? this.node.getChildByName("bg");
if (!bgNode?.isValid) return;
const bgUT = bgNode.getComponent(UITransform);
if (!bgUT) return;
// Bg 节点在 prefab 中挂了 Widget顶底对齐会覆盖代码设置的高度先禁用
const widget = bgNode.getComponent(Widget);
if (widget) widget.enabled = false;
bgUT.height = bgH;
// Bg 锚点在中心,高度为 bgH 时其中心应位于 RichText 顶部向下 bgH/2 处
// RichText 锚点 (0.5,1),其顶部 y = pos.yBg 中心 y = pos.y - bgH/2
const richPos = this.massage_node.node.position;
bgNode.setPosition(bgNode.position.x, richPos.y - bgH / 2, bgNode.position.z);
}
/**
@@ -120,11 +155,9 @@ export class IBoxComp extends CCComp {
private renderSkill(skillUuid: number, lv: number, overrides?: SkillOverrides) {
const skill = SkillSet[skillUuid];
if (!skill) {
this.setHeroName("");
this.setRichText("未知技能");
return;
}
this.setHeroName(skill.name);
this.setRichText(buildSingleSkillRich(skillUuid, overrides, lv));
}
@@ -135,11 +168,9 @@ export class IBoxComp extends CCComp {
private renderEquip(equipUuid: number) {
const equip = findEquipByUuid(equipUuid);
if (!equip) {
this.setHeroName("");
this.setRichText("未知装备");
return;
}
this.setHeroName(equip.name);
this.setRichText(buildEquipRich(equip.field ?? []));
}
@@ -150,20 +181,6 @@ export class IBoxComp extends CCComp {
}
}
/**
* 设置标题名称标签
* @param name 技能/装备名称
*/
private setHeroName(name: string) {
const bgNode = this.node.getChildByName("Bg");
const nameNode = bgNode?.getChildByName("name");
const valNode = nameNode?.getChildByName("val");
const label = valNode?.getComponent(Label) || valNode?.getComponentInChildren(Label);
if (label) {
label.string = name;
}
}
/** 点击弹窗任意区域关闭自身 */
private onTapClose() {
if (this.node && this.node.isValid) {