From 8f47e54b561d2ccb45cb1254a9ce5c3544075d2e Mon Sep 17 00:00:00 2001 From: npmrun <1549469775@qq.com> Date: Sun, 19 Apr 2026 12:41:03 +0800 Subject: [PATCH] feat: add Tween animation utility --- src/core/Game.ts | 5 +++++ src/utils/Tween.ts | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/utils/Tween.ts diff --git a/src/core/Game.ts b/src/core/Game.ts index cfe2e98..241afe9 100644 --- a/src/core/Game.ts +++ b/src/core/Game.ts @@ -7,6 +7,7 @@ import { import { Orientation } from "@/enums/Orientation"; import { initDevtools } from "@pixi/devtools"; import { logger } from "./Logger"; +import { tweenManager } from "@/utils/Tween"; class Game { private static instance: Game; @@ -70,6 +71,10 @@ class Game { this._ticker = Ticker.shared; this._ticker.autoStart = true; + this._ticker.add(() => { + tweenManager.update(); + }); + if (import.meta.env.DEV) { initDevtools({ stage: this._stage, renderer: this._renderer }); } diff --git a/src/utils/Tween.ts b/src/utils/Tween.ts new file mode 100644 index 0000000..5961b38 --- /dev/null +++ b/src/utils/Tween.ts @@ -0,0 +1,50 @@ +import { Group, Tween as TweenJS } from "@tweenjs/tween.js"; + +class TweenManager { + private group: Group; + + constructor() { + this.group = new Group(); + // 在 ticker 中更新 + // 由 Game 更新循环自动处理 + } + + /** + * 创建一个新的 Tween + * @example + * const tween = tweenManager.create({ x: 0, y: 0 }) + * .to({ x: 100, y: 100 }, 1000) + * .onUpdate(obj => { obj.x }) + * .start(); + */ + create(obj: T): TweenJS { + const tween = new TweenJS(obj as object, this.group) as TweenJS; + return tween; + } + + update(time?: number): void { + this.group.update(time); + } + + removeAll(): void { + this.group.removeAll(); + } +} + +export const tweenManager = new TweenManager(); +export default tweenManager; + +// 便捷方法 +export function tweenFromTo( + from: T, + to: Partial, + duration: number, + onUpdate: (obj: T) => void, + onComplete?: () => void +): TweenJS { + const t = tweenManager.create(from).to(to as unknown as object, duration).onUpdate(onUpdate as (obj: object) => void); + if (onComplete) { + t.onComplete(onComplete); + } + return t.start() as TweenJS; +} \ No newline at end of file