import { _decorator, Color, Component, find, Label, Node, Sprite, Tween, tween, UITransform, v3 } from 'cc'; import { PoolManager } from '../core/manager/PoolManager'; import { bundleMgr } from '../core/manager/BundleManager'; import { ResUtil } from './ResUtil'; const { ccclass, property } = _decorator; /** * 通用消息提示框 * 使用示例: * MsgHints.show("这是一条提示消息"); * * 特性: * 1. 使用对象池管理 * 2. 动态创建节点(无需预制体) * 3. 内置Tween动画效果 * 4. 自动回收机制 */ @ccclass("MsgHints") export default class MsgHints extends Component { //节点对象次的名字 private static readonly node_name = "MsgHints"; //默认显示时长(秒) private static readonly default_duration = 1.5; //文本最大宽度 private static readonly max_width = 430; //边距 private static readonly padding = 15; /** * 创建一个msgNode节点 * @returns */ private static createMsgNode() { let node: Node | null = PoolManager.getName(MsgHints.node_name); if(!node){ //创建背景 node = new Node(MsgHints.node_name); node.addComponent(MsgHints); node.active = true; const bgTransform = node.addComponent(UITransform); bgTransform.width = MsgHints.max_width; bgTransform.height = 50; node.setPosition(0, 0, 0); let sp:Sprite = node.addComponent(Sprite); sp.sizeMode = Sprite.SizeMode.TRIMMED; sp.type = Sprite.Type.SIMPLE; ResUtil.setSpriteFrame("msg_hint",sp); //创建文本标签 const labelNode = new Node('label'); const laTransform = labelNode.addComponent(UITransform); laTransform.width = MsgHints.max_width - MsgHints.padding * 2; laTransform.height = 50; let label = labelNode.addComponent(Label); label.fontSize = 25; label.color = Color.WHITE; label.lineHeight = 30; label.horizontalAlign = Label.HorizontalAlign.CENTER; label.verticalAlign = Label.VerticalAlign.CENTER; label.overflow = Label.Overflow.NONE; label.isBold = true; labelNode.parent = node; } return node; } /** * 设置提示消息内容 * @param msg 消息内容 */ public setMsg(msg: string) { let label:Label = this.reset(); if (!label) return; label.string = msg; this._adjustLayout(); this._playAnimation(); } /** * 调整对齐 * @returns */ private _adjustLayout() { let padding: number = 20.0; const label = this.getMsgLable(); const labelTransform = label?.node.getComponent(UITransform); const bgTransform = this.node.getComponent(UITransform); if (!labelTransform || !bgTransform) return; // 计算文本实际宽度(不超过 maxWidth) let labelMax: number = MsgHints.max_width - MsgHints.padding * 2; const textWidth = Math.min(labelTransform.width, MsgHints.max_width - MsgHints.padding * 2); if(textWidth >= labelMax){ label.overflow = Label.Overflow.RESIZE_HEIGHT; labelTransform.width = MsgHints.max_width - padding * 2; bgTransform.width = MsgHints.max_width; bgTransform.height = labelTransform.height + 10; }else{ label.overflow = Label.Overflow.NONE; labelTransform.width = textWidth; bgTransform.width = textWidth + padding * 2; bgTransform.height = labelTransform.height + 10 * 3; } } /** * 播放展示动画 */ private _playAnimation() { Tween.stopAllByTarget(this.node); this.node.setScale(v3(0, 0, 0)); tween(this.node) .to(0.1, { scale: v3(1.1, 1.1, 1) }) .to(0.1, { scale: v3(0.9, 0.9, 1) }) .to(0.1, { scale: v3(1, 1, 1) }) .delay(MsgHints.default_duration) .by(0.5, { position: v3(0, 100, 0) }) .call(() => { this.reset(); PoolManager.putNode(this.node); }) .start(); } /** * 重置lable一些属性 */ public reset(): Label{ let lable:Label = this.getMsgLable(); let laTransform:UITransform = lable.node.getComponent(UITransform); laTransform.width = MsgHints.max_width - MsgHints.padding * 2; laTransform.height = 50; lable.overflow = Label.Overflow.NONE; this.node.setScale(v3(1, 1, 1)); return lable; } /** * 显示提示消息 * @param msg 消息内容 */ public static show(msg: string): Promise { if(!msg)return; //尝试从对象池获取 let node: Node = this.createMsgNode(); //设置节点到Canvas const canvas = find("Canvas"); if (canvas) { node.active = true; node.parent = canvas; //确保在最上层 node.setSiblingIndex(9999); //设置消息内容 const comp = node.getComponent(MsgHints); if (comp) { comp.setMsg(msg); } } } /** * 得到文本节点 */ public getMsgLable(){ return this.node.getChildByName("label").getComponent(Label); } }