直接代码了
把用的技术说一下,单例模式。新建了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) {
}
}