UIInviteSpin.ts 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. import { UIViewID } from '@scripts/define/UIDefine';
  2. import { UIPopup } from '@scripts/framework/ui/UIPopup';
  3. import { addBtnClick } from '@scripts/utils/UIHelper';
  4. import { _decorator, Button, Label, Node, Tween, tween } from 'cc';
  5. const { ccclass, property } = _decorator;
  6. const ITEM_COUNT = 13;
  7. const ITEM_ANGLE = 360 / ITEM_COUNT;
  8. const SPIN_SPEED = 1080; // 匀速阶段:每秒两圈。
  9. const ACCELERATE_TIME = 1;
  10. const LOOP_COUNT = 5;
  11. let testIndex = 0;
  12. @ccclass('UIInviteSpin')
  13. export class UIInviteSpin extends UIPopup {
  14. readonly viewId: UIViewID = UIViewID.UIInviteSpin;
  15. @property(Button)
  16. btnClose: Button;
  17. @property(Button)
  18. btnSpin: Button;
  19. @property(Label)
  20. lblCount: Label;
  21. @property(Node)
  22. btnDiabled: Node;
  23. @property(Node)
  24. turntable: Node;
  25. private spinning = false;
  26. protected onCreate(): void | Promise<void> {
  27. addBtnClick(this.btnClose, this.closeSelf, this);
  28. addBtnClick(this.btnSpin, this.onBtnSpinClick, this);
  29. }
  30. private onBtnSpinClick() {
  31. this.startSpine(testIndex);
  32. testIndex++;
  33. if (testIndex > ITEM_COUNT) testIndex = 0;
  34. }
  35. private startSpine(index: number) {
  36. if (this.spinning || !Number.isInteger(index) || index < 0 || index >= ITEM_COUNT) return;
  37. this.spinning = true;
  38. this.btnClose.interactable = false;
  39. this.btnSpin.interactable = false;
  40. Tween.stopAllByTarget(this.turntable);
  41. const angle = ((this.turntable.angle % 360) + 360) % 360;
  42. this.turntable.angle = angle;
  43. const accAngle = angle + SPIN_SPEED * ACCELERATE_TIME / 2;
  44. const loopAngle = accAngle + 360 * LOOP_COUNT;
  45. // 奖项从顶部开始顺时针排列,转盘正向旋转到对应奖项。
  46. const targetAngle = index * ITEM_ANGLE;
  47. const remainingAngle = ((targetAngle - loopAngle) % 360 + 360) % 360;
  48. const decelerateAngle = 360 * 2 + remainingAngle;
  49. // quadIn/quadOut 的端点速度与匀速段一致,衔接时不会突然变速。
  50. tween(this.turntable)
  51. .to(ACCELERATE_TIME, { angle: accAngle }, { easing: 'quadIn' })
  52. .to(360 * LOOP_COUNT / SPIN_SPEED, { angle: loopAngle }, { easing: 'linear' })
  53. .to(2 * decelerateAngle / SPIN_SPEED,
  54. { angle: loopAngle + decelerateAngle }, { easing: 'quadOut' })
  55. .call(() => {
  56. this.turntable.angle = targetAngle;
  57. this.spinning = false;
  58. this.btnClose.interactable = true;
  59. this.btnSpin.interactable = true;
  60. })
  61. .start();
  62. }
  63. protected onDisable(): void {
  64. Tween.stopAllByTarget(this.turntable);
  65. this.spinning = false;
  66. }
  67. protected onOpen(_params: unknown) {
  68. this.btnClose.interactable = true;
  69. this.btnSpin.interactable = true;
  70. }
  71. }