ToastAni.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. private originalPosition: Vec3 = new Vec3();
  7. private isAnimating: boolean = false;
  8. private currentDuration: number = 2.0; // 默认显示时长(秒)
  9. onLoad() {
  10. // 保存初始位置
  11. this.originalPosition = this.node.position.clone();
  12. // 监听Toast事件
  13. this.setupEventListeners();
  14. // 初始化位置到屏幕左边外侧
  15. this.resetToInitialPosition();
  16. }
  17. private setupEventListeners() {
  18. EventBus.getInstance().on(GameEvents.SHOW_TOAST, this.onShowToast, this);
  19. EventBus.getInstance().on(GameEvents.HIDE_TOAST, this.onHideToast, this);
  20. }
  21. private onShowToast(data: { message: string, duration?: number }) {
  22. if (this.isAnimating) {
  23. return;
  24. }
  25. // 设置显示时长
  26. this.currentDuration = data.duration || 2.0;
  27. // 设置Toast文本
  28. this.setToastMessage(data.message);
  29. // 播放滑入动画
  30. this.playSlideInAnimation();
  31. }
  32. private onHideToast() {
  33. if (!this.isAnimating) {
  34. this.playSlideOutAnimation();
  35. }
  36. }
  37. private setToastMessage(message: string) {
  38. const labelNode = this.node.getChildByName('label');
  39. if (labelNode) {
  40. const label = labelNode.getComponent(Label);
  41. if (label) {
  42. label.string = message;
  43. }
  44. }
  45. }
  46. private resetToInitialPosition() {
  47. // 重置到原始位置(屏幕外侧的起始位置)
  48. this.node.setPosition(this.originalPosition);
  49. }
  50. private playSlideInAnimation() {
  51. if (this.isAnimating) {
  52. return;
  53. }
  54. this.isAnimating = true;
  55. // 确保从起始位置开始
  56. this.resetToInitialPosition();
  57. // 滑入到屏幕中央位置显示
  58. const targetPosition = new Vec3(0, this.originalPosition.y, this.originalPosition.z);
  59. tween(this.node)
  60. .to(0.5, { position: targetPosition }, { easing: 'sineOut' })
  61. .delay(this.currentDuration)
  62. .call(() => {
  63. this.playSlideOutAnimation();
  64. })
  65. .start();
  66. }
  67. private playSlideOutAnimation() {
  68. if (!this.isAnimating) {
  69. return;
  70. }
  71. // 获取Canvas尺寸来计算屏幕边界
  72. const canvas = find('Canvas');
  73. if (canvas) {
  74. const canvasTransform = canvas.getComponent(UITransform);
  75. if (canvasTransform) {
  76. const canvasWidth = canvasTransform.contentSize.width;
  77. // 获取Toast节点的宽度
  78. const toastTransform = this.node.getComponent(UITransform);
  79. const toastWidth = toastTransform ? toastTransform.contentSize.width : 200;
  80. // 滑出到屏幕右边外侧消失
  81. const rightPosition = new Vec3(canvasWidth / 2 + toastWidth / 2 + 50, this.node.position.y, this.node.position.z);
  82. tween(this.node)
  83. .to(0.5, { position: rightPosition }, { easing: 'sineIn' })
  84. .call(() => {
  85. // 动画完成后立即重置到初始位置
  86. this.resetToInitialPosition();
  87. this.isAnimating = false;
  88. })
  89. .start();
  90. }
  91. }
  92. }
  93. onDestroy() {
  94. // 移除事件监听
  95. EventBus.getInstance().off(GameEvents.SHOW_TOAST, this.onShowToast, this);
  96. EventBus.getInstance().off(GameEvents.HIDE_TOAST, this.onHideToast, this);
  97. }
  98. }