MsgHints.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. import { _decorator, Color, Component, find, Label, Node, Sprite, Tween, tween, UITransform, v3 } from 'cc';
  2. import { PoolManager } from '../core/manager/PoolManager';
  3. import { bundleMgr } from '../core/manager/BundleManager';
  4. import { ResUtil } from './ResUtil';
  5. const { ccclass, property } = _decorator;
  6. /**
  7. * 通用消息提示框
  8. * 使用示例:
  9. * MsgHints.show("这是一条提示消息");
  10. *
  11. * 特性:
  12. * 1. 使用对象池管理
  13. * 2. 动态创建节点(无需预制体)
  14. * 3. 内置Tween动画效果
  15. * 4. 自动回收机制
  16. */
  17. @ccclass("MsgHints")
  18. export default class MsgHints extends Component {
  19. //节点对象次的名字
  20. private static readonly node_name = "MsgHints";
  21. //默认显示时长(秒)
  22. private static readonly default_duration = 1.5;
  23. //文本最大宽度
  24. private static readonly max_width = 430;
  25. //边距
  26. private static readonly padding = 15;
  27. /**
  28. * 创建一个msgNode节点
  29. * @returns
  30. */
  31. private static createMsgNode() {
  32. let node: Node | null = PoolManager.getName(MsgHints.node_name);
  33. if(!node){
  34. //创建背景
  35. node = new Node(MsgHints.node_name);
  36. node.addComponent(MsgHints);
  37. node.active = true;
  38. const bgTransform = node.addComponent(UITransform);
  39. bgTransform.width = MsgHints.max_width;
  40. bgTransform.height = 50;
  41. node.setPosition(0, 0, 0);
  42. let sp:Sprite = node.addComponent(Sprite);
  43. sp.sizeMode = Sprite.SizeMode.TRIMMED;
  44. sp.type = Sprite.Type.SIMPLE;
  45. ResUtil.setSpriteFrame("msg_hint",sp);
  46. //创建文本标签
  47. const labelNode = new Node('label');
  48. const laTransform = labelNode.addComponent(UITransform);
  49. laTransform.width = MsgHints.max_width - MsgHints.padding * 2;
  50. laTransform.height = 50;
  51. let label = labelNode.addComponent(Label);
  52. label.fontSize = 25;
  53. label.color = Color.WHITE;
  54. label.lineHeight = 30;
  55. label.horizontalAlign = Label.HorizontalAlign.CENTER;
  56. label.verticalAlign = Label.VerticalAlign.CENTER;
  57. label.overflow = Label.Overflow.NONE;
  58. label.isBold = true;
  59. labelNode.parent = node;
  60. }
  61. return node;
  62. }
  63. /**
  64. * 设置提示消息内容
  65. * @param msg 消息内容
  66. */
  67. public setMsg(msg: string) {
  68. let label:Label = this.reset();
  69. if (!label) return;
  70. label.string = msg;
  71. this._adjustLayout();
  72. this._playAnimation();
  73. }
  74. /**
  75. * 调整对齐
  76. * @returns
  77. */
  78. private _adjustLayout() {
  79. let padding: number = 20.0;
  80. const label = this.getMsgLable();
  81. const labelTransform = label?.node.getComponent(UITransform);
  82. const bgTransform = this.node.getComponent(UITransform);
  83. if (!labelTransform || !bgTransform) return;
  84. // 计算文本实际宽度(不超过 maxWidth)
  85. let labelMax: number = MsgHints.max_width - MsgHints.padding * 2;
  86. const textWidth = Math.min(labelTransform.width, MsgHints.max_width - MsgHints.padding * 2);
  87. if(textWidth >= labelMax){
  88. label.overflow = Label.Overflow.RESIZE_HEIGHT;
  89. labelTransform.width = MsgHints.max_width - padding * 2;
  90. bgTransform.width = MsgHints.max_width;
  91. bgTransform.height = labelTransform.height + 10;
  92. }else{
  93. label.overflow = Label.Overflow.NONE;
  94. labelTransform.width = textWidth;
  95. bgTransform.width = textWidth + padding * 2;
  96. bgTransform.height = labelTransform.height + 10 * 3;
  97. }
  98. }
  99. /**
  100. * 播放展示动画
  101. */
  102. private _playAnimation() {
  103. Tween.stopAllByTarget(this.node);
  104. this.node.setScale(v3(0, 0, 0));
  105. tween(this.node)
  106. .to(0.1, { scale: v3(1.1, 1.1, 1) })
  107. .to(0.1, { scale: v3(0.9, 0.9, 1) })
  108. .to(0.1, { scale: v3(1, 1, 1) })
  109. .delay(MsgHints.default_duration)
  110. .by(0.5, { position: v3(0, 100, 0) })
  111. .call(() => {
  112. this.reset();
  113. PoolManager.putNode(this.node);
  114. })
  115. .start();
  116. }
  117. /**
  118. * 重置lable一些属性
  119. */
  120. public reset(): Label{
  121. let lable:Label = this.getMsgLable();
  122. let laTransform:UITransform = lable.node.getComponent(UITransform);
  123. laTransform.width = MsgHints.max_width - MsgHints.padding * 2;
  124. laTransform.height = 50;
  125. lable.overflow = Label.Overflow.NONE;
  126. this.node.setScale(v3(1, 1, 1));
  127. return lable;
  128. }
  129. /**
  130. * 显示提示消息
  131. * @param msg 消息内容
  132. */
  133. public static show(msg: string): Promise<void> {
  134. if(!msg)return;
  135. //尝试从对象池获取
  136. let node: Node = this.createMsgNode();
  137. //设置节点到Canvas
  138. const canvas = find("Canvas");
  139. if (canvas) {
  140. node.active = true;
  141. node.parent = canvas;
  142. //确保在最上层
  143. node.setSiblingIndex(9999);
  144. //设置消息内容
  145. const comp = node.getComponent(MsgHints);
  146. if (comp) {
  147. comp.setMsg(msg);
  148. }
  149. }
  150. }
  151. /**
  152. * 得到文本节点
  153. */
  154. public getMsgLable(){
  155. return this.node.getChildByName("label").getComponent(Label);
  156. }
  157. }