Skip to content

Commit da79845

Browse files
author
Hardy--Lee
committed
fix: enter exit duration
fix: transform animation type refactor: resume stage object exiting fix: exit animation conflict
1 parent 22084e9 commit da79845

File tree

16 files changed

+393
-421
lines changed

16 files changed

+393
-421
lines changed

packages/webgal/src/Core/Modules/animationFunctions.ts

Lines changed: 204 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@ import { logger } from '@/Core/util/logger';
33
import { generateUniversalSoftOffAnimationObj } from '@/Core/controller/stage/pixi/animations/universalSoftOff';
44
import { webgalStore } from '@/store/store';
55
import cloneDeep from 'lodash/cloneDeep';
6-
import { baseTransform } from '@/store/stageInterface';
6+
import { baseTransform, IEffect, ITransform } from '@/store/stageInterface';
77
import { generateTimelineObj } from '@/Core/controller/stage/pixi/animations/timeline';
88
import { WebGAL } from '@/Core/WebGAL';
9-
import PixiStage, { IAnimationObject } from '@/Core/controller/stage/pixi/PixiController';
10-
import { DEFALUT_FIG_IN_DURATION, DEFALUT_FIG_OUT_DURATION } from '../constants';
9+
import PixiStage, { IAnimationObject, IStageObject } from '@/Core/controller/stage/pixi/PixiController';
10+
import { DEFAULT_STAGE_OBJECT_ENTER_DURATION, DEFAULT_STAGE_OBJECT_EXIT_DURATION } from '../constants';
11+
import { AnimationFrame, IUserAnimation } from './animations';
12+
import { generateTransformAnimationObj } from '../controller/stage/pixi/animations/generateTransformAnimationObj';
13+
import { getNumberArgByKey, getStringArgByKey } from '../util/getSentenceArg';
14+
import { ISentence } from '../controller/scene/sceneInterface';
1115

1216
// eslint-disable-next-line max-params
1317
export function getAnimationObject(animationName: string, target: string, duration: number, writeDefault: boolean) {
@@ -46,52 +50,216 @@ export function getAnimateDuration(animationName: string) {
4650
return 0;
4751
}
4852

53+
/***
54+
* 获取入场或退场动画的对象
55+
* @param target 目标对象
56+
* @param type 动画类型,'enter' 或 'exit'
57+
* @param realTarget 真正的目标对象,用于立绘和背景移除时,打上特殊标记
58+
*/
4959
// eslint-disable-next-line max-params
5060
export function getEnterExitAnimation(
5161
target: string,
5262
type: 'enter' | 'exit',
53-
isBg = false,
54-
realTarget?: string, // 用于立绘和背景移除时,以当前时间打上特殊标记
63+
realTarget?: string,
5564
): {
5665
duration: number;
5766
animation: IAnimationObject | null;
5867
} {
68+
let duration = type === 'enter' ? DEFAULT_STAGE_OBJECT_ENTER_DURATION : DEFAULT_STAGE_OBJECT_EXIT_DURATION;
69+
// 走默认动画
70+
let animation: IAnimationObject | null = null;
71+
let animationName: string | undefined;
5972
if (type === 'enter') {
60-
let duration = DEFALUT_FIG_IN_DURATION;
61-
if (isBg) {
62-
duration = 1500;
63-
}
64-
// 走默认动画
65-
let animation: IAnimationObject | null = generateUniversalSoftInAnimationObj(realTarget ?? target, duration);
66-
67-
const transformState = webgalStore.getState().stage.effects;
68-
const targetEffect = transformState.find((effect) => effect.target === target);
69-
70-
const animarionName = WebGAL.animationManager.nextEnterAnimationName.get(target);
71-
if (animarionName && !targetEffect) {
72-
logger.debug('取代默认进入动画', target);
73-
animation = getAnimationObject(animarionName, realTarget ?? target, getAnimateDuration(animarionName), false);
74-
duration = getAnimateDuration(animarionName);
75-
// 用后重置
73+
animation = generateUniversalSoftInAnimationObj(realTarget ?? target, duration);
74+
animationName = WebGAL.animationManager.nextEnterAnimationName.get(target);
75+
} else {
76+
animation = generateUniversalSoftOffAnimationObj(realTarget ?? target, duration);
77+
animationName = WebGAL.animationManager.nextExitAnimationName.get(target);
78+
}
79+
80+
const transformState = webgalStore.getState().stage.effects;
81+
const targetEffect = transformState.find((effect) => effect.target === target);
82+
83+
if (animationName && !targetEffect) {
84+
logger.debug(`取代默认${type === 'enter' ? '入场' : '退场'}动画`, target);
85+
animation = getAnimationObject(animationName, realTarget ?? target, getAnimateDuration(animationName), false);
86+
duration = getAnimateDuration(animationName);
87+
// 用后重置
88+
if (type === 'enter') {
7689
WebGAL.animationManager.nextEnterAnimationName.delete(target);
90+
} else {
91+
WebGAL.animationManager.nextExitAnimationName.delete(target);
7792
}
78-
return { duration, animation };
93+
}
94+
return { duration, animation };
95+
}
96+
97+
/**
98+
* 创建默认的入场或退场动画
99+
* @param type 动画类型,'enter' 或 'exit'
100+
* @param target 目标对象
101+
* @param frame 应用的动画帧
102+
* @param duration 动画持续时间
103+
* @param ease 缓动类型
104+
*/
105+
// eslint-disable-next-line max-params
106+
export function createDefaultEnterExitAnimation(
107+
type: 'enter' | 'exit',
108+
target: string,
109+
frame: AnimationFrame,
110+
duration: number,
111+
ease: string,
112+
) {
113+
const animationObj = generateTransformAnimationObj(target, frame, duration, ease, type);
114+
const animationName = (Math.random() * 10).toString(16);
115+
const newAnimation: IUserAnimation = { name: animationName, effects: animationObj };
116+
WebGAL.animationManager.addAnimation(newAnimation);
117+
if (type === 'enter') {
118+
WebGAL.animationManager.nextEnterAnimationName.set(target, animationName);
79119
} else {
80-
// exit
81-
let duration = DEFALUT_FIG_OUT_DURATION;
82-
if (isBg) {
83-
duration = 1500;
120+
WebGAL.animationManager.nextExitAnimationName.set(target, animationName);
121+
}
122+
}
123+
124+
// eslint-disable-next-line max-params
125+
export function createEnterExitAnimation(
126+
sentence: ISentence,
127+
targetKey: string,
128+
defaultDuration: number,
129+
currentTransform: ITransform,
130+
): number {
131+
// 处理 transform 和 默认 transform
132+
const transformString = getStringArgByKey(sentence, 'transform');
133+
const ease = getStringArgByKey(sentence, 'ease') ?? '';
134+
let duration = getNumberArgByKey(sentence, 'duration') ?? defaultDuration;
135+
136+
if (transformString) {
137+
console.log(transformString);
138+
try {
139+
const transform = JSON.parse(transformString.toString()) as ITransform;
140+
const enterFrame = { ...transform, duration: 0, ease: '' };
141+
const exitFrame = { ...currentTransform, duration: 0, ease: '' };
142+
createDefaultEnterExitAnimation('enter', targetKey, enterFrame, duration, ease);
143+
createDefaultEnterExitAnimation('exit', targetKey, exitFrame, duration, ease);
144+
} catch (e) {
145+
// 解析都错误了,歇逼吧
146+
applyDefaultTransform();
84147
}
85-
// 走默认动画
86-
let animation: IAnimationObject | null = generateUniversalSoftOffAnimationObj(realTarget ?? target, duration);
87-
const animarionName = WebGAL.animationManager.nextExitAnimationName.get(target);
88-
if (animarionName) {
89-
logger.debug('取代默认退出动画', target);
90-
animation = getAnimationObject(animarionName, realTarget ?? target, getAnimateDuration(animarionName), false);
91-
duration = getAnimateDuration(animarionName);
92-
// 用后重置
93-
WebGAL.animationManager.nextExitAnimationName.delete(target);
148+
} else {
149+
applyDefaultTransform();
150+
}
151+
152+
function applyDefaultTransform() {
153+
const enterFrame = { ...baseTransform, duration: 0, ease: '' };
154+
const exitFrame = { ...currentTransform, duration: 0, ease: '' };
155+
createDefaultEnterExitAnimation('enter', targetKey, enterFrame, duration, ease);
156+
createDefaultEnterExitAnimation('exit', targetKey, exitFrame, duration, ease);
157+
}
158+
159+
const enterAnimation = getStringArgByKey(sentence, 'enter');
160+
const exitAnimation = getStringArgByKey(sentence, 'exit');
161+
if (enterAnimation) {
162+
WebGAL.animationManager.nextEnterAnimationName.set(targetKey, enterAnimation);
163+
duration = getAnimateDuration(enterAnimation);
164+
}
165+
if (exitAnimation) {
166+
WebGAL.animationManager.nextExitAnimationName.set(targetKey, exitAnimation);
167+
duration = getAnimateDuration(exitAnimation);
168+
}
169+
170+
return duration;
171+
}
172+
173+
export function getOldTargetSuffix(): string {
174+
return '-old';
175+
}
176+
177+
export function getOldTargetKey(targetKey: string): string {
178+
const dateString = String(new Date().getTime());
179+
return targetKey + dateString + getOldTargetSuffix();
180+
}
181+
182+
export function getEnterAnimationKey(targetKey: string): string {
183+
return targetKey + '-enter';
184+
}
185+
186+
export function getExitAnimationKey(targetKey: string): string {
187+
return targetKey + '-exit';
188+
}
189+
190+
/**
191+
* 移除指定的场景对象及其动画
192+
* @param targetKey 目标对象的 key
193+
* @param currentEffects 当前场景效果列表
194+
*/
195+
export function removeStageObjectWithAnimationByKey(targetKey: string, currentEffects: IEffect[]) {
196+
// 移除入场动画
197+
const enterAnimationKey = getEnterAnimationKey(targetKey);
198+
WebGAL.gameplay.pixiStage?.removeAnimation(enterAnimationKey, false);
199+
// 快进,跳过退出动画
200+
if (WebGAL.gameplay.isFast) {
201+
logger.debug('快速模式,立刻关闭立绘');
202+
WebGAL.gameplay.pixiStage?.removeStageObjectByKey(targetKey);
203+
return;
204+
}
205+
const oldTarget = WebGAL.gameplay.pixiStage?.getStageObjByKey(targetKey);
206+
if (oldTarget) {
207+
// 修改旧目标的 key, 以避免和新目标冲突
208+
const oldTargetKey = getOldTargetKey(targetKey);
209+
oldTarget.key = oldTargetKey;
210+
// 注册退场动画
211+
const exitAnimationKey = getExitAnimationKey(targetKey);
212+
const { duration, animation } = getEnterExitAnimation(targetKey, 'exit', oldTargetKey);
213+
WebGAL.gameplay.pixiStage?.registerPresetAnimation(animation, exitAnimationKey, oldTargetKey, currentEffects);
214+
// 在动画结束后移除对象及其动画
215+
setTimeout(() => {
216+
WebGAL.gameplay.pixiStage?.removeAnimation(exitAnimationKey, false, false);
217+
WebGAL.gameplay.pixiStage?.removeStageObjectByKey(oldTargetKey);
218+
}, duration);
219+
}
220+
}
221+
222+
/***
223+
* 添加或移除场景对象
224+
* @param targetKey 目标对象的 key
225+
* @param newUrl 新的资源地址
226+
* @param currentEffects 当前场景效果列表
227+
* @param addFunction 添加函数
228+
*/
229+
// eslint-disable-next-line max-params
230+
export function addOrRemoveStageObject(
231+
targetKey: string,
232+
newUrl: string,
233+
currentEffects: IEffect[],
234+
addFunction: Function,
235+
) {
236+
if (newUrl !== '') {
237+
// 如果对象存在且地址不同,移除旧对象, 并添加新对象
238+
const currentStageObject = WebGAL.gameplay.pixiStage?.getStageObjByKey(targetKey);
239+
if (currentStageObject) {
240+
if (currentStageObject.sourceUrl !== newUrl) {
241+
logger.debug(`移除目标 ${targetKey}: ${currentStageObject.sourceUrl}`);
242+
removeStageObjectWithAnimationByKey(targetKey, currentEffects);
243+
// 添加新对象
244+
logger.debug(`新增目标 ${targetKey}: ${newUrl}`);
245+
addFunction();
246+
// 注册入场动画
247+
const enterAnimationKey = getEnterAnimationKey(targetKey);
248+
const { duration, animation } = getEnterExitAnimation(targetKey, 'enter');
249+
WebGAL.gameplay.pixiStage!.registerPresetAnimation(animation, enterAnimationKey, targetKey, currentEffects);
250+
}
251+
} else {
252+
// 如果对象不存在,添加新对象
253+
logger.debug(`新增目标 ${targetKey}: ${newUrl}`);
254+
addFunction();
255+
// 注册入场动画
256+
const enterAnimationKey = getEnterAnimationKey(targetKey);
257+
const { duration, animation } = getEnterExitAnimation(targetKey, 'enter');
258+
WebGAL.gameplay.pixiStage!.registerPresetAnimation(animation, enterAnimationKey, targetKey, currentEffects);
94259
}
95-
return { duration, animation };
260+
} else {
261+
// 如果新地址为空,移除对象
262+
logger.debug(`移除目标 ${targetKey}`);
263+
removeStageObjectWithAnimationByKey(targetKey, currentEffects);
96264
}
97265
}
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
export const STAGE_KEYS = {
22
STAGE_MAIN: 'stage-main',
3-
BGMAIN: 'bg-main',
4-
FIG_C: 'fig-center',
5-
FIG_L: 'fig-left',
6-
FIG_R: 'fig-right',
3+
BG_MAIN: 'bg-main',
4+
FIG_CENTER: 'fig-center',
5+
FIG_LEFT: 'fig-left',
6+
FIG_RIGHT: 'fig-right',
77
};
88

99
export const WEBGAL_NONE = 'none';
10-
export const DEFALUT_FIG_IN_DURATION = 300;
11-
export const DEFALUT_FIG_OUT_DURATION = 450;
10+
export const DEFAULT_STAGE_OBJECT_ENTER_DURATION = 300;
11+
export const DEFAULT_STAGE_OBJECT_EXIT_DURATION = 450;

0 commit comments

Comments
 (0)