ButtonManager.ts 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import { _decorator, Component, Node, Button, Tween, tween, Vec3 } from 'cc';
  2. const { ccclass, property } = _decorator;
  3. @ccclass('ButtonManager')
  4. export class ButtonManager extends Component {
  5. private static _instance: ButtonManager = null;
  6. @property({ type: [Button], displayName: "按钮数组" })
  7. public buttons: Button[] = [];
  8. // 存储每个按钮的原始缩放值
  9. private buttonOriginalScales: Map<Node, Vec3> = new Map();
  10. // 动画参数
  11. private readonly SCALE_REDUCTION = 0.15; // 缩放减少量
  12. private readonly ANIMATION_DURATION = 0.1; // 动画持续时间
  13. public static get instance(): ButtonManager {
  14. return ButtonManager._instance;
  15. }
  16. onLoad() {
  17. // 设置单例
  18. if (ButtonManager._instance === null) {
  19. ButtonManager._instance = this;
  20. } else {
  21. this.destroy();
  22. return;
  23. }
  24. // 初始化按钮事件
  25. this.initButtonEvents();
  26. }
  27. onDestroy() {
  28. if (ButtonManager._instance === this) {
  29. ButtonManager._instance = null;
  30. }
  31. }
  32. private initButtonEvents() {
  33. this.buttons.forEach((button, index) => {
  34. if (button && button.node) {
  35. // 存储按钮的原始缩放值
  36. this.buttonOriginalScales.set(button.node, button.node.scale.clone());
  37. // 添加点击事件监听
  38. button.node.on(Button.EventType.CLICK, () => {
  39. this.playClickAnimation(button.node);
  40. }, this);
  41. }
  42. });
  43. }
  44. /**
  45. * 播放按钮点击动画
  46. * @param buttonNode 按钮节点
  47. */
  48. private playClickAnimation(buttonNode: Node) {
  49. if (!buttonNode) return;
  50. // 停止之前的动画
  51. Tween.stopAllByTarget(buttonNode);
  52. // 获取按钮的原始缩放值
  53. const originalScale = this.buttonOriginalScales.get(buttonNode);
  54. if (!originalScale) {
  55. // 如果没有存储原始缩放值,则使用当前缩放值作为原始值
  56. const currentScale = buttonNode.scale.clone();
  57. this.buttonOriginalScales.set(buttonNode, currentScale);
  58. return this.playClickAnimation(buttonNode);
  59. }
  60. // 先恢复到原始缩放,确保动画基准正确
  61. buttonNode.scale = originalScale.clone();
  62. // 计算目标缩放值(基于原始缩放减去0.15)
  63. const targetScale = new Vec3(
  64. Math.max(0.1, originalScale.x - this.SCALE_REDUCTION), // 最小缩放限制为0.1
  65. Math.max(0.1, originalScale.y - this.SCALE_REDUCTION),
  66. originalScale.z
  67. );
  68. // 创建缩放动画:先缩小,然后回到原始大小
  69. tween(buttonNode)
  70. .to(this.ANIMATION_DURATION, { scale: targetScale })
  71. .to(this.ANIMATION_DURATION, { scale: originalScale })
  72. .start();
  73. }
  74. /**
  75. * 手动添加按钮到管理器
  76. * @param button 要添加的按钮
  77. */
  78. public addButton(button: Button) {
  79. if (button && this.buttons.indexOf(button) === -1) {
  80. this.buttons.push(button);
  81. // 为新添加的按钮设置事件
  82. if (button.node) {
  83. // 存储按钮的原始缩放值
  84. this.buttonOriginalScales.set(button.node, button.node.scale.clone());
  85. button.node.on(Button.EventType.CLICK, () => {
  86. this.playClickAnimation(button.node);
  87. }, this);
  88. }
  89. }
  90. }
  91. /**
  92. * 从管理器中移除按钮
  93. * @param button 要移除的按钮
  94. */
  95. public removeButton(button: Button) {
  96. const index = this.buttons.indexOf(button);
  97. if (index !== -1) {
  98. // 移除事件监听
  99. if (button.node) {
  100. button.node.off(Button.EventType.CLICK, this.playClickAnimation, this);
  101. // 清除存储的原始缩放值
  102. this.buttonOriginalScales.delete(button.node);
  103. }
  104. this.buttons.splice(index, 1);
  105. }
  106. }
  107. /**
  108. * 清空所有按钮
  109. */
  110. public clearAllButtons() {
  111. this.buttons.forEach(button => {
  112. if (button && button.node) {
  113. button.node.off(Button.EventType.CLICK, this.playClickAnimation, this);
  114. }
  115. });
  116. // 清空原始缩放值存储
  117. this.buttonOriginalScales.clear();
  118. this.buttons = [];
  119. }
  120. }