feat(SinfoComp): 新增信息弹窗关闭按钮功能

1. 给SInfoBox预制体添加关闭按钮配置项
2. 新增close_btn节点绑定与自动兜底查找逻辑
3. 重构全局触摸关闭逻辑,改为精确判断触点位置
4. 分离弹窗自身点击和关闭按钮点击的事件处理
5. 统一添加按钮点击音效播放逻辑
This commit is contained in:
pan
2026-08-27 14:52:50 +08:00
parent b2f474d73b
commit 434ab91f81
2 changed files with 40 additions and 5 deletions

View File

@@ -1691,6 +1691,9 @@
"lv3_desc": {
"__id__": 185
},
"close_btn": {
"__id__": 95
},
"_id": ""
},
{

View File

@@ -25,7 +25,7 @@
* - SkillCardList / EquipPoolList(卡牌静态配置)
* - HeroSkillDesc(buildCardDescRich 富文本描述生成)
*/
import { _decorator, Node, Label, RichText, NodeEventType, Sprite, Color, input, Input, EventTouch } from "cc";
import { _decorator, Node, Label, RichText, NodeEventType, Sprite, Color, input, Input, EventTouch, UITransform, Vec3 } 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 { oops } from "db://oops-framework/core/Oops";
@@ -104,6 +104,10 @@ export class SinfoComp extends CCComp {
@property({ type: RichText, displayName: "3级提升说明" })
private lv3_desc: RichText = null;
/** 关闭按钮节点 */
@property({ type: Node, displayName: "关闭按钮" })
private close_btn: Node = null;
// ======================== 运行时状态 ========================
/** 弹窗参数 */
@@ -112,8 +116,13 @@ export class SinfoComp extends CCComp {
// ======================== 生命周期 ========================
onLoad() {
// 点击弹窗自身(BlockInputEvents 拦截)不关闭,仅点击外部遮罩关闭
// 点击弹窗自身:阻止冒泡,由全局触摸判定触点位置决定是否关闭
this.node.on(NodeEventType.TOUCH_END, this.onSelfTouch, this);
// 关闭按钮:编辑器未绑定时按节点名 "close" 兜底查找
if (!this.close_btn) {
this.close_btn = this.node.getChildByName("close");
}
this.close_btn?.on(NodeEventType.TOUCH_END, this.onCloseClick, this);
}
onDestroy() {
@@ -121,6 +130,9 @@ export class SinfoComp extends CCComp {
if (this.node && this.node.isValid) {
this.node.off(NodeEventType.TOUCH_END, this.onSelfTouch, this);
}
if (this.close_btn && this.close_btn.isValid) {
this.close_btn.off(NodeEventType.TOUCH_END, this.onCloseClick, this);
}
// 注销全局触摸监听
input.off(Input.EventType.TOUCH_END, this.onGlobalTouch, this);
}
@@ -143,12 +155,32 @@ export class SinfoComp extends CCComp {
event.propagationStopped = true;
}
/** 全局触摸结束:点击弹窗外部关闭 */
private onGlobalTouch() {
// 若点击落在弹窗内部(被 BlockInputEvents 拦截)则不会走到这里
/** 关闭按钮点击 */
private onCloseClick(event: EventTouch) {
// 阻止冒泡,避免同时触发 onSelfTouch / onGlobalTouch 双重关闭
event.propagationStopped = true;
oops.audio.playEffect("music/button");
this.close();
}
/** 全局触摸结束:触点落在弹窗包围盒外才关闭 */
private onGlobalTouch(event: EventTouch) {
if (!this.node || !this.node.isValid) return;
// 触点 UI 坐标 → 弹窗局部坐标,判定是否在弹窗内(convertToNodeSpaceAR 需要 Vec3)
const uit = this.node.getComponent(UITransform);
if (!uit) return;
const uiPos = event.getUILocation();
const localPos = uit.convertToNodeSpaceAR(new Vec3(uiPos.x, uiPos.y, 0));
const halfW = uit.contentSize.width * uit.anchorX;
const halfH = uit.contentSize.height * uit.anchorY;
const inBox =
localPos.x >= -halfW && localPos.x <= uit.contentSize.width - halfW &&
localPos.y >= -halfH && localPos.y <= uit.contentSize.height - halfH;
if (!inBox) {
this.close();
}
}
/** 关闭弹窗 */
private close() {
oops.gui.removeByNode(this.node);