ToastAni.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import { _decorator, Component, Node, UITransform, Label, tween, Vec3, find } from 'cc';
  2. import EventBus, { GameEvents } from '../Core/EventBus';
  3. const { ccclass, property } = _decorator;
  4. @ccclass('ToastAni')
  5. export class ToastAni extends Component {
  6. @property({
  7. displayName: "Toast类型",
  8. tooltip: "选择Toast的类型:wave表示波次提示,resource表示资源不足提示"
  9. })
  10. public toastType: string = 'wave'; // 'wave' 或 'resource'
  11. private originalPosition: Vec3 = new Vec3();
  12. private isAnimating: boolean = false;
  13. private currentDuration: number = 0; // 默认显示时长(秒)
  14. onLoad() {
  15. // 保存初始位置
  16. this.originalPosition = this.node.position.clone();
  17. // 监听Toast事件
  18. this.setupEventListeners();
  19. // 初始化位置到屏幕左边外侧
  20. this.resetToInitialPosition();
  21. }
  22. private setupEventListeners() {
  23. const eventBus = EventBus.getInstance();
  24. if (this.toastType === 'wave') {
  25. // 波次提示Toast监听原有事件
  26. eventBus.on(GameEvents.SHOW_TOAST, this.onShowToast, this);
  27. eventBus.on(GameEvents.HIDE_TOAST, this.onHideToast, this);
  28. } else if (this.toastType === 'resource') {
  29. // 资源不足Toast监听新事件
  30. eventBus.on(GameEvents.SHOW_RESOURCE_TOAST, this.onShowToast, this);
  31. eventBus.on(GameEvents.HIDE_RESOURCE_TOAST, this.onHideToast, this);
  32. }
  33. }
  34. private onShowToast(data: { message: string, duration?: number }) {
  35. if (this.isAnimating) {
  36. return;
  37. }
  38. // 设置Toast文本
  39. this.setToastMessage(data.message);
  40. // 播放滑入动画
  41. this.playSlideInAnimation();
  42. }
  43. private onHideToast() {
  44. if (!this.isAnimating) {
  45. this.playSlideOutAnimation();
  46. }
  47. }
  48. private setToastMessage(message: string) {
  49. const labelNode = this.node.getChildByName('label');
  50. if (labelNode) {
  51. const label = labelNode.getComponent(Label);
  52. if (label) {
  53. label.string = message;
  54. }
  55. }
  56. }
  57. private resetToInitialPosition() {
  58. // 重置到原始位置(屏幕外侧的起始位置)
  59. this.node.setPosition(this.originalPosition);
  60. }
  61. private playSlideInAnimation() {
  62. if (this.isAnimating) {
  63. return;
  64. }
  65. this.isAnimating = true;
  66. // 确保从起始位置开始
  67. this.resetToInitialPosition();
  68. // 滑入到屏幕中央位置显示
  69. const targetPosition = new Vec3(0, this.originalPosition.y, this.originalPosition.z);
  70. tween(this.node)
  71. .to(0.5, { position: targetPosition }, { easing: 'sineOut' })
  72. .delay(0.5)
  73. .call(() => {
  74. this.playSlideOutAnimation();
  75. })
  76. .start();
  77. }
  78. private playSlideOutAnimation() {
  79. if (!this.isAnimating) {
  80. return;
  81. }
  82. // 获取Canvas尺寸来计算屏幕边界
  83. const canvas = find('Canvas');
  84. if (canvas) {
  85. const canvasTransform = canvas.getComponent(UITransform);
  86. if (canvasTransform) {
  87. const canvasWidth = canvasTransform.contentSize.width;
  88. // 获取Toast节点的宽度
  89. const toastTransform = this.node.getComponent(UITransform);
  90. const toastWidth = toastTransform ? toastTransform.contentSize.width : 200;
  91. // 滑出到屏幕右边外侧消失
  92. const rightPosition = new Vec3(canvasWidth / 2 + toastWidth / 2 + 50, this.node.position.y, this.node.position.z);
  93. tween(this.node)
  94. .to(0.5, { position: rightPosition }, { easing: 'sineIn' })
  95. .call(() => {
  96. // 动画完成后立即重置到初始位置
  97. this.resetToInitialPosition();
  98. this.isAnimating = false;
  99. })
  100. .start();
  101. }
  102. }
  103. }
  104. onDestroy() {
  105. // 移除事件监听
  106. const eventBus = EventBus.getInstance();
  107. if (this.toastType === 'wave') {
  108. // 移除波次提示Toast事件监听
  109. eventBus.off(GameEvents.SHOW_TOAST, this.onShowToast, this);
  110. eventBus.off(GameEvents.HIDE_TOAST, this.onHideToast, this);
  111. } else if (this.toastType === 'resource') {
  112. // 移除资源不足Toast事件监听
  113. eventBus.off(GameEvents.SHOW_RESOURCE_TOAST, this.onShowToast, this);
  114. eventBus.off(GameEvents.HIDE_RESOURCE_TOAST, this.onHideToast, this);
  115. }
  116. }
  117. }