| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- import { _decorator, Component, Node, tween, Tween, Vec3, UIOpacity } from 'cc';
- const { ccclass, property } = _decorator;
- /**
- * MenuAni
- * 菜单动画控制器
- * 提供菜单相关的动画效果
- */
- @ccclass('MenuAni')
- export class MenuAni extends Component {
- /** 动画持续时间 */
- @property({ tooltip: '动画持续时间(秒)' })
- public animationDuration: number = 0.3;
-
- /** 淡入淡出动画的目标节点 */
- @property({ type: Node, tooltip: '执行淡入淡出动画的目标节点' })
- public fadeTarget: Node = null;
-
- /** 缩放动画的目标节点 */
- @property({ type: Node, tooltip: '执行缩放动画的目标节点' })
- public scaleTarget: Node = null;
-
- private _originalScale: Vec3 = new Vec3();
-
- onLoad() {
- // 保存原始缩放值
- if (this.scaleTarget) {
- this._originalScale.set(this.scaleTarget.scale);
- }
- }
-
- /**
- * 淡入动画
- * @param target 目标节点,如果不指定则使用fadeTarget
- * @param duration 动画时长,如果不指定则使用animationDuration
- */
- public fadeIn(target?: Node, duration?: number): Promise<void> {
- const animTarget = target || this.fadeTarget;
- const animDuration = duration !== undefined ? duration : this.animationDuration;
-
- if (!animTarget) {
- console.warn('[MenuAni] fadeIn: 未指定目标节点');
- return Promise.resolve();
- }
-
- return new Promise<void>((resolve) => {
- // 获取UIOpacity组件
- let uiOpacity = animTarget.getComponent(UIOpacity);
- if (!uiOpacity) {
- console.warn(`[MenuAni] fadeIn: 节点 ${animTarget.name} 缺少UIOpacity组件,请手动添加`);
- return;
- }
-
- // 停止现有动画
- Tween.stopAllByTarget(uiOpacity);
-
- // 设置初始透明度
- uiOpacity.opacity = 0;
-
- // 执行淡入动画
- tween(uiOpacity)
- .to(animDuration, { opacity: 255 }, { easing: 'quadOut' })
- .call(() => {
- resolve();
- })
- .start();
- });
- }
-
- /**
- * 淡出动画
- * @param target 目标节点,如果不指定则使用fadeTarget
- * @param duration 动画时长,如果不指定则使用animationDuration
- */
- public fadeOut(target?: Node, duration?: number): Promise<void> {
- const animTarget = target || this.fadeTarget;
- const animDuration = duration !== undefined ? duration : this.animationDuration;
-
- if (!animTarget) {
- console.warn('[MenuAni] fadeOut: 未指定目标节点');
- return Promise.resolve();
- }
-
- return new Promise<void>((resolve) => {
- // 获取UIOpacity组件
- let uiOpacity = animTarget.getComponent(UIOpacity);
- if (!uiOpacity) {
- console.warn(`[MenuAni] fadeOut: 节点 ${animTarget.name} 缺少UIOpacity组件,请手动添加`);
- return;
- }
-
- // 停止现有动画
- Tween.stopAllByTarget(uiOpacity);
-
- // 执行淡出动画
- tween(uiOpacity)
- .to(animDuration, { opacity: 0 }, { easing: 'quadIn' })
- .call(() => {
- resolve();
- })
- .start();
- });
- }
-
- /**
- * 缩放弹出动画
- * @param target 目标节点,如果不指定则使用scaleTarget
- * @param duration 动画时长,如果不指定则使用animationDuration
- */
- public scalePopIn(target?: Node, duration?: number): Promise<void> {
- const animTarget = target || this.scaleTarget;
- const animDuration = duration !== undefined ? duration : this.animationDuration;
-
- if (!animTarget) {
- console.warn('[MenuAni] scalePopIn: 未指定目标节点');
- return Promise.resolve();
- }
-
- return new Promise<void>((resolve) => {
- // 停止现有动画
- Tween.stopAllByTarget(animTarget);
-
- // 设置初始缩放
- animTarget.setScale(0, 0, 1);
-
- // 执行弹出动画
- tween(animTarget)
- .to(animDuration, { scale: this._originalScale }, { easing: 'backOut' })
- .call(() => {
- resolve();
- })
- .start();
- });
- }
-
- /**
- * 缩放收缩动画
- * @param target 目标节点,如果不指定则使用scaleTarget
- * @param duration 动画时长,如果不指定则使用animationDuration
- */
- public scalePopOut(target?: Node, duration?: number): Promise<void> {
- const animTarget = target || this.scaleTarget;
- const animDuration = duration !== undefined ? duration : this.animationDuration;
-
- if (!animTarget) {
- console.warn('[MenuAni] scalePopOut: 未指定目标节点');
- return Promise.resolve();
- }
-
- return new Promise<void>((resolve) => {
- // 停止现有动画
- Tween.stopAllByTarget(animTarget);
-
- // 执行收缩动画
- tween(animTarget)
- .to(animDuration, { scale: new Vec3(0, 0, 1) }, { easing: 'backIn' })
- .call(() => {
- resolve();
- })
- .start();
- });
- }
-
- /**
- * 组合动画:淡入 + 缩放弹出
- * @param fadeTarget 淡入动画目标节点
- * @param scaleTarget 缩放动画目标节点
- * @param duration 动画时长
- */
- public async fadeInWithScale(fadeTarget?: Node, scaleTarget?: Node, duration?: number): Promise<void> {
- const promises: Promise<void>[] = [];
-
- if (fadeTarget || this.fadeTarget) {
- promises.push(this.fadeIn(fadeTarget, duration));
- }
-
- if (scaleTarget || this.scaleTarget) {
- promises.push(this.scalePopIn(scaleTarget, duration));
- }
-
- await Promise.all(promises);
- }
-
- /**
- * 组合动画:淡出 + 缩放收缩
- * @param fadeTarget 淡出动画目标节点
- * @param scaleTarget 缩放动画目标节点
- * @param duration 动画时长
- */
- public async fadeOutWithScale(fadeTarget?: Node, scaleTarget?: Node, duration?: number): Promise<void> {
- const promises: Promise<void>[] = [];
-
- if (fadeTarget || this.fadeTarget) {
- promises.push(this.fadeOut(fadeTarget, duration));
- }
-
- if (scaleTarget || this.scaleTarget) {
- promises.push(this.scalePopOut(scaleTarget, duration));
- }
-
- await Promise.all(promises);
- }
-
- /**
- * 停止所有动画
- */
- public stopAllAnimations() {
- if (this.fadeTarget) {
- const uiOpacity = this.fadeTarget.getComponent(UIOpacity);
- if (uiOpacity) {
- Tween.stopAllByTarget(uiOpacity);
- }
- }
-
- if (this.scaleTarget) {
- Tween.stopAllByTarget(this.scaleTarget);
- }
- }
-
- /**
- * 重置所有目标节点到初始状态
- */
- public resetToInitialState() {
- this.stopAllAnimations();
-
- if (this.fadeTarget) {
- let uiOpacity = this.fadeTarget.getComponent(UIOpacity);
- if (uiOpacity) {
- uiOpacity.opacity = 255;
- }
- }
-
- if (this.scaleTarget) {
- this.scaleTarget.setScale(this._originalScale);
- }
- }
- }
|