Skip to content

Commit b592494

Browse files
author
Hardy--Lee
committed
fix: enter exit duration
1 parent fd35764 commit b592494

File tree

19 files changed

+393
-393
lines changed

19 files changed

+393
-393
lines changed

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

Lines changed: 197 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ 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';
9+
import PixiStage, { IAnimationObject, IStageObject } from '@/Core/controller/stage/pixi/PixiController';
10+
import { AnimationFrame, IUserAnimation } from './animations';
11+
import { generateTransformAnimationObj } from '../controller/stage/pixi/animations/generateTransformAnimationObj';
12+
import { getNumberArgByKey, getStringArgByKey } from '../util/getSentenceArg';
13+
import { ISentence } from '../controller/scene/sceneInterface';
1014

1115
// eslint-disable-next-line max-params
1216
export function getAnimationObject(animationName: string, target: string, duration: number, writeDefault: boolean) {
@@ -45,51 +49,210 @@ export function getAnimateDuration(animationName: string) {
4549
return 0;
4650
}
4751

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

0 commit comments

Comments
 (0)