feat: 提交资源
This commit is contained in:
290
assets/scripts/DialogBox.ts
Normal file
290
assets/scripts/DialogBox.ts
Normal file
@@ -0,0 +1,290 @@
|
||||
import { _decorator, Button, Component, director, Label, Node, tween, Vec3 } from "cc";
|
||||
|
||||
/**
|
||||
* DialogBox配置选项接口
|
||||
*/
|
||||
export interface IDialogBoxOptions {
|
||||
/** 标题,默认为"提示" */
|
||||
title?: string;
|
||||
/** 内容,默认为空 */
|
||||
content?: string;
|
||||
/** 确定回调,可选 */
|
||||
onConfirm?: () => void;
|
||||
/** 取消回调,可选 */
|
||||
onCancel?: () => void;
|
||||
/** 确定按钮文本,默认为"确定" */
|
||||
confirmText?: string;
|
||||
/** 取消按钮文本,默认为"取消" */
|
||||
cancelText?: string;
|
||||
/** 是否显示取消按钮,默认为true */
|
||||
showCancel?: boolean;
|
||||
/** 场景中DialogBox节点名称,默认为"DialogBox" */
|
||||
dialogNodeName?: string;
|
||||
hideClose?: boolean;
|
||||
}
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
/**
|
||||
* 基础对话框组件
|
||||
*/
|
||||
@ccclass("DialogBox")
|
||||
export class DialogBox extends Component {
|
||||
// 静态缓存场景中的DialogBox节点
|
||||
private static sceneDialogBox: DialogBox | null = null;
|
||||
private static dialogNode: Node | null = null;
|
||||
|
||||
@property(Label)
|
||||
titleLabel: Label = null!;
|
||||
|
||||
@property(Label)
|
||||
contentLabel: Label = null!;
|
||||
|
||||
@property(Button)
|
||||
confirmBtn: Button = null!;
|
||||
|
||||
@property(Label)
|
||||
confirmBtnLabel: Label = null!;
|
||||
|
||||
@property(Button)
|
||||
cancelBtn: Button = null!;
|
||||
|
||||
@property(Label)
|
||||
cancelBtnLabel: Label = null!;
|
||||
|
||||
// 回调函数
|
||||
private onConfirmCallback: (() => void) | null = null;
|
||||
private onCancelCallback: (() => void) | null = null;
|
||||
|
||||
start() {
|
||||
// 绑定按钮事件
|
||||
if (this.confirmBtn) {
|
||||
this.confirmBtn.node.on(Button.EventType.CLICK, this.onConfirmClick, this);
|
||||
}
|
||||
|
||||
if (this.cancelBtn) {
|
||||
this.cancelBtn.node.on(Button.EventType.CLICK, this.onCancelClick, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置对话框内容
|
||||
* @param options 配置选项
|
||||
*/
|
||||
public setContent(options: IDialogBoxOptions = {}): void {
|
||||
const {
|
||||
title = "提示",
|
||||
content = "",
|
||||
onConfirm,
|
||||
onCancel,
|
||||
confirmText = "确定",
|
||||
cancelText = "取消",
|
||||
showCancel = true,
|
||||
} = options;
|
||||
|
||||
// 设置标题和内容
|
||||
if (this.titleLabel) {
|
||||
this.titleLabel.string = title;
|
||||
}
|
||||
if (this.contentLabel) {
|
||||
this.contentLabel.string = content;
|
||||
}
|
||||
|
||||
// 设置按钮文本
|
||||
if (this.confirmBtnLabel) {
|
||||
this.confirmBtnLabel.string = confirmText;
|
||||
}
|
||||
if (this.cancelBtnLabel) {
|
||||
this.cancelBtnLabel.string = cancelText;
|
||||
}
|
||||
|
||||
// 控制取消按钮显示状态
|
||||
if (this.cancelBtn) {
|
||||
this.cancelBtn.node.active = showCancel;
|
||||
}
|
||||
|
||||
// 保存回调函数
|
||||
this.onConfirmCallback = onConfirm || null;
|
||||
this.onCancelCallback = onCancel || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示对话框(带弹出动画)
|
||||
*/
|
||||
public show(): void {
|
||||
this.node.active = true;
|
||||
|
||||
// 初始化缩放和透明度
|
||||
this.node.setScale(Vec3.ZERO);
|
||||
|
||||
// 弹出动画:缩放从0到1,带回弹效果
|
||||
tween(this.node)
|
||||
.to(
|
||||
0.3,
|
||||
{ scale: Vec3.ONE },
|
||||
{
|
||||
easing: "backOut", // 回弹缓动效果
|
||||
},
|
||||
)
|
||||
.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 隐藏对话框(带关闭动画)
|
||||
*/
|
||||
public hide(): void {
|
||||
// 停止所有动画
|
||||
tween(this.node).stop();
|
||||
|
||||
// 关闭动画:缩放到0
|
||||
tween(this.node)
|
||||
.to(
|
||||
0.2,
|
||||
{ scale: Vec3.ZERO },
|
||||
{
|
||||
easing: "backIn", // 回缩缓动效果
|
||||
},
|
||||
)
|
||||
.call(() => {
|
||||
// 动画结束后隐藏节点
|
||||
this.node.active = false;
|
||||
// 恢复缩放值,为下次显示做准备
|
||||
this.node.setScale(Vec3.ONE);
|
||||
})
|
||||
.start();
|
||||
|
||||
// 清理回调
|
||||
this.onConfirmCallback = null;
|
||||
this.onCancelCallback = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 确定按钮点击事件
|
||||
*/
|
||||
private onConfirmClick(): void {
|
||||
// 执行回调
|
||||
if (this.onConfirmCallback) {
|
||||
this.onConfirmCallback();
|
||||
}
|
||||
|
||||
// 隐藏对话框
|
||||
this.hide();
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消按钮点击事件
|
||||
*/
|
||||
private onCancelClick(): void {
|
||||
// 执行回调
|
||||
if (this.onCancelCallback) {
|
||||
this.onCancelCallback();
|
||||
}
|
||||
|
||||
// 隐藏对话框
|
||||
this.hide();
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
// 清理事件监听
|
||||
if (this.confirmBtn) {
|
||||
this.confirmBtn.node.off(Button.EventType.CLICK, this.onConfirmClick, this);
|
||||
}
|
||||
|
||||
if (this.cancelBtn) {
|
||||
this.cancelBtn.node.off(Button.EventType.CLICK, this.onCancelClick, this);
|
||||
}
|
||||
|
||||
// 停止所有动画
|
||||
tween(this.node).stop();
|
||||
|
||||
// 清理静态引用
|
||||
if (DialogBox.sceneDialogBox === this) {
|
||||
DialogBox.sceneDialogBox = null;
|
||||
DialogBox.dialogNode = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法:显示对话框
|
||||
* @param options 配置选项
|
||||
*/
|
||||
public static showDialog(options: IDialogBoxOptions = {}): void {
|
||||
const { dialogNodeName = "DialogBox" } = options;
|
||||
|
||||
// 获取场景中的DialogBox节点
|
||||
if (!DialogBox.sceneDialogBox || !DialogBox.dialogNode?.isValid) {
|
||||
DialogBox.findDialogBoxInScene(dialogNodeName);
|
||||
}
|
||||
|
||||
if (!DialogBox.sceneDialogBox) {
|
||||
return; // 场景中未找到DialogBox节点
|
||||
}
|
||||
|
||||
// 设置内容并显示
|
||||
DialogBox.sceneDialogBox.setContent(options);
|
||||
DialogBox.sceneDialogBox.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法:隐藏当前对话框(带动画)
|
||||
*/
|
||||
public static hideCurrentDialog(): void {
|
||||
if (DialogBox.sceneDialogBox) {
|
||||
DialogBox.sceneDialogBox.hide();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 静态方法:立即隐藏当前对话框(无动画)
|
||||
*/
|
||||
public static hideCurrentDialogImmediately(): void {
|
||||
if (DialogBox.sceneDialogBox) {
|
||||
// 停止所有动画
|
||||
tween(DialogBox.sceneDialogBox.node).stop();
|
||||
// 立即隐藏
|
||||
DialogBox.sceneDialogBox.node.active = false;
|
||||
DialogBox.sceneDialogBox.node.setScale(Vec3.ONE);
|
||||
// 清理回调
|
||||
DialogBox.sceneDialogBox.onConfirmCallback = null;
|
||||
DialogBox.sceneDialogBox.onCancelCallback = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 在场景中查找DialogBox节点
|
||||
* @param nodeName 节点名称
|
||||
*/
|
||||
private static findDialogBoxInScene(nodeName: string): void {
|
||||
const scene = director.getScene();
|
||||
if (!scene) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 递归查找DialogBox节点
|
||||
const findNodeRecursively = (node: Node, targetName: string): Node | null => {
|
||||
if (node.name === targetName) {
|
||||
return node;
|
||||
}
|
||||
|
||||
for (const child of node.children) {
|
||||
const found = findNodeRecursively(child, targetName);
|
||||
if (found) {
|
||||
return found;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const dialogNode = findNodeRecursively(scene, nodeName);
|
||||
if (dialogNode) {
|
||||
const dialogComponent = dialogNode.getComponent(DialogBox);
|
||||
if (dialogComponent) {
|
||||
DialogBox.sceneDialogBox = dialogComponent;
|
||||
DialogBox.dialogNode = dialogNode;
|
||||
// 初始状态为隐藏
|
||||
dialogNode.active = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user