import { _decorator, Component, Node, tween, Tween, Vec3 } from 'cc'; import type { TweenEasing } from 'cc'; const { ccclass, property } = _decorator; @ccclass('BlinkScaleAnimator') export default class BlinkScaleAnimator extends Component { @property({ tooltip: '放大比例因子(相对于初始缩放)' }) public scaleFactor: number = 1.3; @property({ tooltip: '放大阶段时长(秒)' }) public upDuration: number = 0.15; @property({ tooltip: '缩小阶段时长(秒)' }) public downDuration: number = 0.15; @property({ tooltip: '放大阶段缓动' }) public easingUp: TweenEasing | ((k: number) => number) = 'sineOut'; @property({ tooltip: '缩小阶段缓动' }) public easingDown: TweenEasing | ((k: number) => number) = 'sineIn'; @property({ tooltip: '启用组件时自动开始闪烁' }) public playOnEnable: boolean = true; private _originalScale: Vec3 = Vec3.ONE.clone(); private _blinkTween: Tween | null = null; onLoad() { this._originalScale = this.node.scale.clone(); } onEnable() { if (this.playOnEnable) { this.play(); } } onDisable() { this.stop(); } onDestroy() { this.stop(); } public play(): void { this.stop(); const targetScale = new Vec3( this._originalScale.x * this.scaleFactor, this._originalScale.y * this.scaleFactor, this._originalScale.z ); this._blinkTween = tween(this.node) .to(this.upDuration, { scale: targetScale }, { easing: this.easingUp }) .to(this.downDuration, { scale: this._originalScale }, { easing: this.easingDown }) .union() .repeatForever() .start(); } public stop(): void { if (this._blinkTween) { this._blinkTween.stop(); this._blinkTween = null; } Tween.stopAllByTarget(this.node); // 恢复初始缩放 this.node.scale = this._originalScale.clone(); } // 自动挂载并启动闪烁 public static ensure(node: Node, options?: Partial<{ scaleFactor: number, upDuration: number, downDuration: number, easingUp: TweenEasing | ((k: number) => number), easingDown: TweenEasing | ((k: number) => number), playOnEnable: boolean, }>): BlinkScaleAnimator { let comp = node.getComponent(BlinkScaleAnimator); if (!comp) { comp = node.addComponent(BlinkScaleAnimator); } if (options) { if (options.scaleFactor !== undefined) comp.scaleFactor = options.scaleFactor; if (options.upDuration !== undefined) comp.upDuration = options.upDuration; if (options.downDuration !== undefined) comp.downDuration = options.downDuration; if (options.easingUp !== undefined) comp.easingUp = options.easingUp; if (options.easingDown !== undefined) comp.easingDown = options.easingDown; if (options.playOnEnable !== undefined) comp.playOnEnable = options.playOnEnable; } comp.play(); return comp; } }