import { Node, tween, Tween, Vec3 } from 'cc'; /** 放大阶段(秒) */ const PULSE_UP_SEC = 0.4; /** 峰顶停留(秒) */ const PULSE_PEAK_SEC = 0.14; /** 缩回阶段(秒) */ const PULSE_DOWN_SEC = 0.4; /** 峰顶 Y 偏移(像素) */ const PULSE_LIFT_Y = 6; /** 跳动形变代理(sx/sy 相对基准 scale 的倍率) */ interface PulsePose { sx: number; sy: number; y: number; } /** * BattleGame btnItem 循环跳动:非等比 scale(拉宽/拉高)+ 轻微上浮。 */ export class BattleGameItemAdBtnPulse { private _node: Node | null = null; private readonly _baseScale = new Vec3(1, 1, 1); private _baseX = 0; private _baseY = 0; private _baseZ = 0; private _loopTween: Tween | null = null; private readonly _pose: PulsePose = { sx: 1, sy: 1, y: 0 }; private readonly _onPulseUpdate = (): void => { this._applyPose(); }; /** 绑定节点并启动循环跳动 */ bind(node: Node | null): void { this.unbind(); if (!node?.isValid) return; this._node = node; const p = node.position; const s = node.scale; this._baseX = p.x; this._baseY = p.y; this._baseZ = p.z; this._baseScale.set(s.x, s.y, s.z); this._resetPose(); this._startLoop(); } /** 停止跳动并还原节点姿态 */ unbind(): void { const node = this._node; if (this._loopTween) { this._loopTween.stop(); this._loopTween = null; } if (node?.isValid) { Tween.stopAllByTarget(node); Tween.stopAllByTarget(this._pose); node.setScale(this._baseScale); node.setPosition(this._baseX, this._baseY, this._baseZ); } this._node = null; } /** 循环宽高形变脉冲 */ private _startLoop(): void { const node = this._node; if (!node?.isValid) return; const pose = this._pose; this._resetPose(); const opts = { onUpdate: this._onPulseUpdate }; this._loopTween = tween(pose) .repeatForever( tween(pose) .to(PULSE_UP_SEC, { sx: 0.96, sy: 1.12, y: PULSE_LIFT_Y * 0.65, }, { easing: 'sineInOut', ...opts }) .to(PULSE_PEAK_SEC, { sx: 1.14, sy: 0.90, y: PULSE_LIFT_Y, }, { easing: 'sineOut', ...opts }) .to(PULSE_DOWN_SEC, { sx: 1, sy: 1, y: 0, }, { easing: 'sineInOut', ...opts }), ) .start(); } /** 将代理姿态应用到节点 */ private _applyPose(): void { const node = this._node; if (!node?.isValid) return; const p = this._pose; node.setScale(this._baseScale.x * p.sx, this._baseScale.y * p.sy, 1); node.setPosition(this._baseX, this._baseY + p.y, this._baseZ); } /** 重置代理到常态 */ private _resetPose(): void { this._pose.sx = 1; this._pose.sy = 1; this._pose.y = 0; } }