给cocos 3.8 消息控制器

直接代码了

把用的技术说一下,单例模式。新建了node ,添加 内容。重点是背景,用的 Graphics 组件,用 SpriteFrame 必须引入图片,这里用了单色,其实停简单的,里面自己看看,可以修改一下

javascript 复制代码
import { _decorator, Component, Node, Label, Button, Graphics, UITransform, Vec3, tween, Tween, UIOpacity, Color, EventTouch, find, director } from 'cc';
const { ccclass, property } = _decorator;

export enum MessageType {
    INFO = 'info',
    SUCCESS = 'success',
    WARNING = 'warning',
    ERROR = 'error'
}

@ccclass('messageManager')
export class messageManager extends Component {
    private static instance: messageManager | null = null;
    
    private toastQueue: { message: string; type: MessageType; duration: number }[] = [];
    private isShowingToast: boolean = false;
    
    private alertQueue: { title: string; message: string; confirmCallback?: () => void; cancelCallback?: () => void; showCancel?: boolean }[] = [];
    private isShowingAlert: boolean = false;

    public static get Instance(): messageManager {
        if (!messageManager.instance) {
            const node = new Node();
            node.name = "MessageSystem";
            
            let canvas = find("Canvas");
            if (!canvas) {
                const scene = director.getScene();
                if (scene) canvas = scene;
            }
            
            if (canvas) {
                canvas.addChild(node);
            } else {
                console.error("无法找到Canvas节点,消息系统将无法显示");
                const scene = director.getScene();
                if (scene) scene.addChild(node);
                else node.parent = node;
            }
            
            messageManager.instance = node.addComponent(messageManager);
        }
        return messageManager.instance;
    }

    static showToast(message: string, type: MessageType = MessageType.INFO, duration: number = 2.5) {
        messageManager.Instance?.showToastMessage(message, type, duration);
    }

    private showToastMessage(message: string, type: MessageType, duration: number) {
        this.toastQueue.push({ message, type, duration });
        if (!this.isShowingToast) this.processToastQueue();
    }

    private processToastQueue() {
        if (this.toastQueue.length === 0) {
            this.isShowingToast = false;
            return;
        }

        this.isShowingToast = true;
        const { message, type, duration } = this.toastQueue.shift()!;
        this.createToastNode(message, type, duration);
    }

    private createToastNode(message: string, type: MessageType, duration: number) {
        const toastNode = new Node();
        toastNode.name = "Toast";
        this.node.addChild(toastNode);
        toastNode.setPosition(0, 0, 0);
        
        let toastTransform = toastNode.getComponent(UITransform);
        if (!toastTransform) toastTransform = toastNode.addComponent(UITransform);
        toastTransform.setContentSize(500, 100);
        toastTransform.setAnchorPoint(0.5, 0.5);
        
        // 背景 - 使用 Graphics
        const bgNode = new Node();
        bgNode.name = "Background";
        toastNode.addChild(bgNode);
        bgNode.setPosition(0, 0, 0);
        
        const bgGraphics = bgNode.addComponent(Graphics);
        bgGraphics.fillColor = this.getBackgroundColor(type);
        bgGraphics.rect(-250, -50, 500, 100); // 居中绘制
        bgGraphics.fill();
        
        let bgTransform = bgNode.getComponent(UITransform);
        if (!bgTransform) bgTransform = bgNode.addComponent(UITransform);
        bgTransform.setContentSize(500, 100);
        bgTransform.setAnchorPoint(0.5, 0.5);
        
        // 文本
        const labelNode = new Node();
        labelNode.name = "Label";
        toastNode.addChild(labelNode);
        labelNode.setPosition(0, 0, 0);
        
        const label = labelNode.addComponent(Label);
        label.string = message;
        label.fontSize = 36;
        label.lineHeight = 44;
        label.color = Color.WHITE;
        
        let labelTransform = labelNode.getComponent(UITransform);
        if (!labelTransform) labelTransform = labelNode.addComponent(UITransform);
        labelTransform.setContentSize(460, 80);
        labelTransform.setAnchorPoint(0.5, 0.5);
        
        // 动画
        const opacityComp = toastNode.addComponent(UIOpacity);
        opacityComp.opacity = 0;
        
        tween(toastNode)
            .by(0.3, { position: new Vec3(0, 50, 0) })
            .start();
        
        tween(opacityComp)
            .to(0.3, { opacity: 255 })
            .delay(duration)
            .to(0.3, { opacity: 0 })
            .call(() => {
                toastNode.destroy();
                this.processToastQueue();
            })
            .start();
    }

    static showAlert(
        title: string, 
        message: string, 
        confirmCallback?: () => void, 
        cancelCallback?: () => void, 
        showCancel: boolean = false
    ) {
        messageManager.Instance?.showAlertDialog(
            title, 
            message, 
            confirmCallback, 
            cancelCallback, 
            showCancel
        );
    }

    private showAlertDialog(
        title: string, 
        message: string, 
        confirmCallback?: () => void, 
        cancelCallback?: () => void, 
        showCancel: boolean = false
    ) {
        this.alertQueue.push({
            title, 
            message, 
            confirmCallback, 
            cancelCallback, 
            showCancel
        });
        
        if (!this.isShowingAlert) this.processAlertQueue();
    }

    private processAlertQueue() {
        if (this.alertQueue.length === 0) {
            this.isShowingAlert = false;
            return;
        }

        this.isShowingAlert = true;
        const { title, message, confirmCallback, cancelCallback, showCancel } = this.alertQueue.shift()!;
        this.createAlertNode(title, message, confirmCallback, cancelCallback, showCancel);
    }

    private createAlertNode(
        title: string, 
        message: string, 
        confirmCallback?: () => void, 
        cancelCallback?: () => void, 
        showCancel: boolean = false
    ) {
        // 遮罩层 - 使用 Graphics
        const maskNode = new Node();
        maskNode.name = "AlertMask";
        this.node.addChild(maskNode);
        maskNode.setPosition(0, 0, 0);
        
        const maskGraphics = maskNode.addComponent(Graphics);
        maskGraphics.fillColor = new Color(0, 0, 0, 150);
        maskGraphics.rect(-1000, -1000, 2000, 2000);
        maskGraphics.fill();
        
        let maskTransform = maskNode.getComponent(UITransform);
        if (!maskTransform) maskTransform = maskNode.addComponent(UITransform);
        maskTransform.setContentSize(2000, 2000);
        maskTransform.setAnchorPoint(0.5, 0.5);
        
        const maskOpacity = maskNode.addComponent(UIOpacity);
        maskOpacity.opacity = 0;
        
        // 对话框
        const dialogNode = new Node();
        dialogNode.name = "AlertDialog";
        maskNode.addChild(dialogNode);
        dialogNode.setPosition(0, 0, 0);
        
        let dialogTransform = dialogNode.getComponent(UITransform);
        if (!dialogTransform) dialogTransform = dialogNode.addComponent(UITransform);
        dialogTransform.setContentSize(600, 400);
        dialogTransform.setAnchorPoint(0.5, 0.5);
        
        // 背景 - 使用 Graphics
        const bgNode = new Node();
        bgNode.name = "Background";
        dialogNode.addChild(bgNode);
        bgNode.setPosition(0, 0, 0);
        
        const bgGraphics = bgNode.addComponent(Graphics);
        bgGraphics.fillColor = new Color(50, 50, 50, 255);
        bgGraphics.rect(-300, -200, 600, 400);
        bgGraphics.fill();
        
        let bgTransform = bgNode.getComponent(UITransform);
        if (!bgTransform) bgTransform = bgNode.addComponent(UITransform);
        bgTransform.setContentSize(600, 400);
        bgTransform.setAnchorPoint(0.5, 0.5);
        
        // 标题
        const titleNode = new Node();
        titleNode.name = "Title";
        dialogNode.addChild(titleNode);
        titleNode.setPosition(0, 150, 0);
        
        const titleLabel = titleNode.addComponent(Label);
        titleLabel.string = title;
        titleLabel.fontSize = 42;
        titleLabel.lineHeight = 50;
        titleLabel.color = Color.YELLOW;
        
        let titleTransform = titleNode.getComponent(UITransform);
        if (!titleTransform) titleTransform = titleNode.addComponent(UITransform);
        titleTransform.setContentSize(560, 60);
        titleTransform.setAnchorPoint(0.5, 0.5);
        
        // 消息
        const messageNode = new Node();
        messageNode.name = "Message";
        dialogNode.addChild(messageNode);
        messageNode.setPosition(0, 50, 0);
        
        const messageLabel = messageNode.addComponent(Label);
        messageLabel.string = message;
        messageLabel.fontSize = 36;
        messageLabel.lineHeight = 44;
        messageLabel.color = Color.WHITE;
        
        let messageTransform = messageNode.getComponent(UITransform);
        if (!messageTransform) messageTransform = messageNode.addComponent(UITransform);
        messageTransform.setContentSize(560, 120);
        messageTransform.setAnchorPoint(0.5, 0.5);
        
        // 按钮容器
        const buttonContainer = new Node();
        buttonContainer.name = "ButtonContainer";
        dialogNode.addChild(buttonContainer);
        buttonContainer.setPosition(0, -100, 0);
        
        // 确定按钮 - 使用 Graphics
        const confirmButtonNode = new Node();
        confirmButtonNode.name = "ConfirmButton";
        buttonContainer.addChild(confirmButtonNode);
        confirmButtonNode.setPosition(showCancel ? -110 : 0, 0, 0);
        
        const confirmButton = confirmButtonNode.addComponent(Button);
        const confirmGraphics = confirmButtonNode.addComponent(Graphics);
        confirmGraphics.fillColor = new Color(70, 130, 180, 255);
        confirmGraphics.rect(-100, -30, 200, 60);
        confirmGraphics.fill();
        
        let confirmTransform = confirmButtonNode.getComponent(UITransform);
        if (!confirmTransform) confirmTransform = confirmButtonNode.addComponent(UITransform);
        confirmTransform.setContentSize(200, 60);
        confirmTransform.setAnchorPoint(0.5, 0.5);
        
        const confirmLabelNode = new Node();
        confirmLabelNode.name = "Label";
        confirmButtonNode.addChild(confirmLabelNode);
        confirmLabelNode.setPosition(0, 0, 0);
        
        const confirmLabel = confirmLabelNode.addComponent(Label);
        confirmLabel.string = "确定";
        confirmLabel.fontSize = 32;
        confirmLabel.color = Color.WHITE;
        
        let confirmLabelTransform = confirmLabelNode.getComponent(UITransform);
        if (!confirmLabelTransform) confirmLabelTransform = confirmLabelNode.addComponent(UITransform);
        confirmLabelTransform.setContentSize(200, 60);
        confirmLabelTransform.setAnchorPoint(0.5, 0.5);
        
        // 取消按钮
        let cancelButtonNode: Node | null = null;
        if (showCancel) {
            cancelButtonNode = new Node();
            cancelButtonNode.name = "CancelButton";
            buttonContainer.addChild(cancelButtonNode);
            cancelButtonNode.setPosition(110, 0, 0);
            
            const cancelButton = cancelButtonNode.addComponent(Button);
            const cancelGraphics = cancelButtonNode.addComponent(Graphics);
            cancelGraphics.fillColor = new Color(120, 120, 120, 255);
            cancelGraphics.rect(-100, -30, 200, 60);
            cancelGraphics.fill();
            
            let cancelTransform = cancelButtonNode.getComponent(UITransform);
            if (!cancelTransform) cancelTransform = cancelButtonNode.addComponent(UITransform);
            cancelTransform.setContentSize(200, 60);
            cancelTransform.setAnchorPoint(0.5, 0.5);
            
            const cancelLabelNode = new Node();
            cancelLabelNode.name = "Label";
            cancelButtonNode.addChild(cancelLabelNode);
            cancelLabelNode.setPosition(0, 0, 0);
            
            const cancelLabel = cancelLabelNode.addComponent(Label);
            cancelLabel.string = "取消";
            cancelLabel.fontSize = 32;
            cancelLabel.color = Color.WHITE;
            
            let cancelLabelTransform = cancelLabelNode.getComponent(UITransform);
            if (!cancelLabelTransform) cancelLabelTransform = cancelLabelNode.addComponent(UITransform);
            cancelLabelTransform.setContentSize(200, 60);
            cancelLabelTransform.setAnchorPoint(0.5, 0.5);
        }
        
        // 事件
        confirmButtonNode.on(Node.EventType.TOUCH_END, () => {
            this.closeAlert(maskNode, confirmCallback);
        }, this);
        
        if (cancelButtonNode) {
            cancelButtonNode.on(Node.EventType.TOUCH_END, () => {
                this.closeAlert(maskNode, cancelCallback);
            }, this);
        }
        
        // 动画
        tween(maskOpacity)
            .to(0.3, { opacity: 255 })
            .start();
    }

    private closeAlert(maskNode: Node, callback?: () => void) {
        const opacityComp = maskNode.getComponent(UIOpacity);
        if (opacityComp) {
            tween(opacityComp)
                .to(0.3, { opacity: 0 })
                .call(() => {
                    maskNode.destroy();
                    if (callback) callback();
                    this.processAlertQueue();
                })
                .start();
        }
    }

    private getBackgroundColor(type: MessageType): Color {
        switch (type) {
            case MessageType.SUCCESS: return new Color(46, 125, 50, 220);
            case MessageType.WARNING: return new Color(237, 108, 2, 220);
            case MessageType.ERROR: return new Color(211, 47, 47, 220);
            default: return new Color(2, 119, 189, 220);
        }
    }
}

这是使用方法

javascript 复制代码
import { _decorator, Color, Component, Node, resources, Sprite, SpriteFrame, UITransform } from 'cc';
import { messageManager, MessageType } from './messageManager';
const { ccclass, property } = _decorator;

@ccclass('NewComponent')
export class NewComponent extends Component {


    // 示例使用
    start() {
  
        // 显示普通信息
        // messageManager.showToast("这是一个普通提示");

        // // 显示成功消息(绿色)
        // messageManager.showToast("操作成功完成!", MessageType.SUCCESS);

        // // 显示警告消息(橙色)
        // messageManager.showToast("磁盘空间不足", MessageType.WARNING, 3.0);

        // // 显示错误消息(红色)
        // messageManager.showToast("网络连接失败,请重试", MessageType.ERROR, 4.0);




        messageManager.showAlert("确认", "确定要删除此项吗?", () => {
            console.log("用户点击了确定");
            // 执行删除操作
        });

        // 带取消按钮的提示框
        messageManager.showAlert(
            "退出游戏", 
            "确定要退出游戏吗?", 
            () => {
                console.log("用户确认退出");
                // 退出游戏逻辑
            },
            () => {
                console.log("用户取消退出");
            },
            true // 显示取消按钮
        );

    }

    update(deltaTime: number) {
        
    }
}
相关推荐
廋到被风吹走2 小时前
【JAVA】【JDK】java8版本之后各个版本调整
java·开发语言
林恒smileZAZ2 小时前
vue对接海康摄像头-H5player
前端·javascript·vue.js
韩曙亮2 小时前
【Web APIs】移动端返回顶部案例 ( 返回顶部按钮 显示 / 隐藏 设置 | 返回顶部操作 )
前端·javascript·css·html·移动端·web apis·返回顶部
悟能不能悟2 小时前
如何处理java.time包类序列化问题,跨版本反序列化 Class对象可能抛出 InvalidClassException
java·开发语言
xxxxxxllllllshi2 小时前
深入解析单例模式:从原理到实战,掌握Java面试高频考点
java·开发语言·单例模式·面试
=PNZ=BeijingL2 小时前
SprintBoot +Screw+PostgreSQL生成数据库文档时空指针问题
开发语言·c#
L-岁月染过的梦2 小时前
前端使用JS实现端口探活
开发语言·前端·javascript
idealzouhu2 小时前
【Android】深入浅出 JNI
android·开发语言·python·jni
廋到被风吹走2 小时前
【Java】【Jdk】Jdk11->Jdk17
java·开发语言·jvm