update
This commit is contained in:
@@ -15,6 +15,10 @@ export enum PageTransitionType {
|
||||
NONE = "none",
|
||||
SLIDE_LEFT = "slide_left",
|
||||
SLIDE_RIGHT = "slide_right",
|
||||
SLIDE_UP = "slide_up",
|
||||
SLIDE_DOWN = "slide_down",
|
||||
FADE = "fade",
|
||||
SCALE = "scale",
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,6 +41,15 @@ export interface PageTransitionConfig {
|
||||
simultaneous?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* 子面板动画配置接口
|
||||
*/
|
||||
export interface SubPanelAnimationConfig {
|
||||
openAnimation: PageTransitionType;
|
||||
closeAnimation: PageTransitionType;
|
||||
duration?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 导航管理器
|
||||
*
|
||||
@@ -172,10 +185,14 @@ export class NavigationManager {
|
||||
|
||||
private subPanelDic: Map<Node, Node[]> = new Map();
|
||||
private subPanelMapping: Map<Node, PanelType> = new Map();
|
||||
private subPanelAnimationConfigs: Map<Node, SubPanelAnimationConfig> = new Map();
|
||||
|
||||
// 弹窗管理相关属性
|
||||
private popupPanels: Set<Node> = new Set(); // 管理所有打开的弹窗
|
||||
|
||||
// 动画锁,防止动画中重复操作
|
||||
private isAnimating: boolean = false;
|
||||
|
||||
/**
|
||||
* 统一的subPanel清理方法
|
||||
* @param basePanel 主面板节点
|
||||
@@ -198,6 +215,9 @@ export class NavigationManager {
|
||||
// 清理subPanelMapping
|
||||
this.subPanelMapping.delete(subPanel);
|
||||
|
||||
// 清理动画配置
|
||||
this.subPanelAnimationConfigs.delete(subPanel);
|
||||
|
||||
if (destroyPanels) {
|
||||
const baseView = subPanel.getComponent(li_BaseView);
|
||||
if (baseView) {
|
||||
@@ -212,7 +232,12 @@ export class NavigationManager {
|
||||
// 清理subPanelDic
|
||||
this.subPanelDic.delete(basePanel);
|
||||
}
|
||||
public openSubPanel(panelName: string, basePanel: Node, data: any = null) {
|
||||
public openSubPanel(
|
||||
panelName: string,
|
||||
basePanel: Node,
|
||||
data: any = null,
|
||||
animationConfig?: SubPanelAnimationConfig
|
||||
) {
|
||||
if (!panelName) {
|
||||
console.error("[NavigationManager] openSubPanel: panelName is empty");
|
||||
return;
|
||||
@@ -223,6 +248,14 @@ export class NavigationManager {
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用默认动画配置
|
||||
const defaultConfig: SubPanelAnimationConfig = {
|
||||
openAnimation: PageTransitionType.SCALE,
|
||||
closeAnimation: PageTransitionType.SCALE,
|
||||
duration: 0.3
|
||||
};
|
||||
const config = animationConfig || defaultConfig;
|
||||
|
||||
const callback = (n: Node) => {
|
||||
if (!n || !n.isValid) {
|
||||
console.error("[NavigationManager] openSubPanel: created panel is invalid");
|
||||
@@ -243,12 +276,171 @@ export class NavigationManager {
|
||||
console.warn(`[NavigationManager] 无法确定basePanel类型: ${basePanel.name}`);
|
||||
}
|
||||
|
||||
n.setParent(basePanel, true);
|
||||
|
||||
// 存储动画配置
|
||||
this.subPanelAnimationConfigs.set(n, config);
|
||||
|
||||
// 执行打开动画
|
||||
this.playSubPanelOpenAnimation(n, config);
|
||||
};
|
||||
|
||||
ViewManager.I.openBundlesView(panelName, data, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支持自定义动画方向的面板切换方法
|
||||
* @param panelType 目标面板类型
|
||||
* @param transitionConfig 过渡动画配置
|
||||
* @param force 是否强制切换
|
||||
*/
|
||||
public switchToPanelWithTransition(
|
||||
panelType: PanelType,
|
||||
transitionConfig: PageTransitionConfig,
|
||||
force: boolean = false
|
||||
): Node {
|
||||
if (!panelType) {
|
||||
console.error("[NavigationManager] switchToPanelWithTransition: panelType is invalid");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this.currentActivePanelType === panelType && !force) {
|
||||
console.log(`[NavigationManager] Already on ${panelType}, skipping switch`);
|
||||
return this.currentActivePanel;
|
||||
}
|
||||
|
||||
if (!this.navigationPanel) {
|
||||
console.warn(
|
||||
"[NavigationManager] NavigationPanel not registered, fallback to direct ViewManager call"
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 切换面板前先关闭所有弹窗
|
||||
this.closeAllPopups();
|
||||
|
||||
// 通知NavigationPanel显示加载状态
|
||||
this.navigationPanel.showLoading?.();
|
||||
|
||||
// 获取动画方向
|
||||
const hideDirection = this.getDirectionFromTransitionType(transitionConfig.outgoingTransition);
|
||||
const showDirection = this.getDirectionFromTransitionType(transitionConfig.incomingTransition);
|
||||
|
||||
// 隐藏当前面板(包括子页面)
|
||||
if (this.currentActivePanel && this.currentActivePanel.isValid) {
|
||||
this.hidePanelWithAnimation(this.currentActivePanel, hideDirection);
|
||||
}
|
||||
|
||||
// 加载并显示目标面板
|
||||
this.loadOrGetPanel(panelType, (panel: Node) => {
|
||||
this.currentActivePanelType = panelType;
|
||||
|
||||
// 更新NavigationPanel按钮状态
|
||||
this.navigationPanel.updateButtonStates?.(panelType);
|
||||
|
||||
// 显示面板
|
||||
this.showPanelWithAnimation(panel, showDirection, () => {
|
||||
this.currentActivePanel = panel;
|
||||
this.navigationPanel.hideLoading?.();
|
||||
});
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将过渡类型转换为方向字符串
|
||||
*/
|
||||
private getDirectionFromTransitionType(transitionType: PageTransitionType): "left" | "right" | "up" | "down" {
|
||||
switch (transitionType) {
|
||||
case PageTransitionType.SLIDE_LEFT:
|
||||
return "left";
|
||||
case PageTransitionType.SLIDE_RIGHT:
|
||||
return "right";
|
||||
case PageTransitionType.SLIDE_UP:
|
||||
return "up";
|
||||
case PageTransitionType.SLIDE_DOWN:
|
||||
return "down";
|
||||
default:
|
||||
return "left"; // 默认向左
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行子面板打开动画
|
||||
*/
|
||||
private playSubPanelOpenAnimation(panel: Node, config: SubPanelAnimationConfig): void {
|
||||
if (!panel || !panel.isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const duration = config.duration || 0.3;
|
||||
|
||||
switch (config.openAnimation) {
|
||||
case PageTransitionType.SCALE:
|
||||
UITransitionHelper.scaleIn(panel, duration);
|
||||
break;
|
||||
case PageTransitionType.FADE:
|
||||
UITransitionHelper.fadeIn(panel, duration);
|
||||
break;
|
||||
case PageTransitionType.SLIDE_UP:
|
||||
UITransitionHelper.slideInFromBottom(panel, duration);
|
||||
break;
|
||||
case PageTransitionType.SLIDE_DOWN:
|
||||
UITransitionHelper.slideInFromTop(panel, duration);
|
||||
break;
|
||||
case PageTransitionType.SLIDE_LEFT:
|
||||
UITransitionHelper.slideInFromRight(panel, duration);
|
||||
break;
|
||||
case PageTransitionType.SLIDE_RIGHT:
|
||||
UITransitionHelper.slideInFromLeft(panel, duration);
|
||||
break;
|
||||
default:
|
||||
// 无动画,直接显示
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行子面板关闭动画
|
||||
*/
|
||||
private playSubPanelCloseAnimation(
|
||||
panel: Node,
|
||||
config: SubPanelAnimationConfig,
|
||||
callback?: Function
|
||||
): void {
|
||||
if (!panel || !panel.isValid) {
|
||||
callback && callback();
|
||||
return;
|
||||
}
|
||||
|
||||
const duration = config.duration || 0.3;
|
||||
|
||||
switch (config.closeAnimation) {
|
||||
case PageTransitionType.SCALE:
|
||||
UITransitionHelper.scaleOut(panel, duration, callback);
|
||||
break;
|
||||
case PageTransitionType.FADE:
|
||||
UITransitionHelper.fadeOut(panel, duration, callback);
|
||||
break;
|
||||
case PageTransitionType.SLIDE_UP:
|
||||
UITransitionHelper.slideOutToTop(panel, duration, callback);
|
||||
break;
|
||||
case PageTransitionType.SLIDE_DOWN:
|
||||
UITransitionHelper.slideOutToBottom(panel, duration, callback);
|
||||
break;
|
||||
case PageTransitionType.SLIDE_LEFT:
|
||||
UITransitionHelper.slideOutToLeft(panel, duration, callback);
|
||||
break;
|
||||
case PageTransitionType.SLIDE_RIGHT:
|
||||
UITransitionHelper.slideOutToRight(panel, duration, callback);
|
||||
break;
|
||||
default:
|
||||
// 无动画,直接执行回调
|
||||
callback && callback();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开弹窗面板
|
||||
* @param panelName 弹窗面板名称
|
||||
@@ -330,7 +522,7 @@ export class NavigationManager {
|
||||
// 确保清空集合
|
||||
this.popupPanels.clear();
|
||||
}
|
||||
public closeSubPanel(panel: Node | li_BaseView) {
|
||||
public closeSubPanel(panel: Node | li_BaseView, animationConfig?: SubPanelAnimationConfig) {
|
||||
if (!panel) {
|
||||
console.warn("[NavigationManager] closeSubPanel: panel is null or undefined");
|
||||
return;
|
||||
@@ -348,6 +540,41 @@ export class NavigationManager {
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取动画配置(优先使用传入的配置,然后使用存储的配置,最后使用默认配置)
|
||||
let config = animationConfig;
|
||||
if (!config && this.subPanelAnimationConfigs.has(panelNode)) {
|
||||
config = this.subPanelAnimationConfigs.get(panelNode);
|
||||
}
|
||||
if (!config) {
|
||||
config = {
|
||||
openAnimation: PageTransitionType.SCALE,
|
||||
closeAnimation: PageTransitionType.SCALE,
|
||||
duration: 0.3
|
||||
};
|
||||
}
|
||||
|
||||
// 执行关闭动画
|
||||
this.playSubPanelCloseAnimation(panelNode, config, () => {
|
||||
// 从管理映射中移除
|
||||
this.removeSubPanelFromMappings(panelNode);
|
||||
|
||||
// 销毁或关闭panel
|
||||
try {
|
||||
if (panel instanceof Node) {
|
||||
panel.destroy();
|
||||
} else {
|
||||
panel.close();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[NavigationManager] closeSubPanel error:", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 从管理映射中移除子面板
|
||||
*/
|
||||
private removeSubPanelFromMappings(panelNode: Node): void {
|
||||
// 从subPanelMapping和subPanelDic中移除
|
||||
if (this.subPanelMapping.has(panelNode)) {
|
||||
const baseType = this.subPanelMapping.get(panelNode);
|
||||
@@ -370,15 +597,9 @@ export class NavigationManager {
|
||||
this.subPanelMapping.delete(panelNode);
|
||||
}
|
||||
|
||||
// 销毁或关闭panel
|
||||
try {
|
||||
if (panel instanceof Node) {
|
||||
panel.destroy();
|
||||
} else {
|
||||
panel.close();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[NavigationManager] closeSubPanel error:", error);
|
||||
// 移除动画配置
|
||||
if (this.subPanelAnimationConfigs.has(panelNode)) {
|
||||
this.subPanelAnimationConfigs.delete(panelNode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,7 +710,7 @@ export class NavigationManager {
|
||||
*/
|
||||
private hidePanelWithAnimation(
|
||||
panel: Node,
|
||||
direction: "left" | "right",
|
||||
direction: "left" | "right" | "up" | "down",
|
||||
callback?: Function
|
||||
) {
|
||||
if (!panel || !panel.isValid || !panel.active) {
|
||||
@@ -504,10 +725,23 @@ export class NavigationManager {
|
||||
callback && callback();
|
||||
};
|
||||
|
||||
if (direction === "left") {
|
||||
UITransitionHelper.slideOutToLeft(panel, 0.3, animationCallback);
|
||||
} else {
|
||||
UITransitionHelper.slideOutToRight(panel, 0.3, animationCallback);
|
||||
switch (direction) {
|
||||
case "left":
|
||||
UITransitionHelper.slideOutToLeft(panel, 0.3, animationCallback);
|
||||
break;
|
||||
case "right":
|
||||
UITransitionHelper.slideOutToRight(panel, 0.3, animationCallback);
|
||||
break;
|
||||
case "up":
|
||||
UITransitionHelper.slideOutToTop(panel, 0.3, animationCallback);
|
||||
break;
|
||||
case "down":
|
||||
UITransitionHelper.slideOutToBottom(panel, 0.3, animationCallback);
|
||||
break;
|
||||
default:
|
||||
// 默认左侧滑出
|
||||
UITransitionHelper.slideOutToLeft(panel, 0.3, animationCallback);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,7 +750,7 @@ export class NavigationManager {
|
||||
*/
|
||||
private showPanelWithAnimation(
|
||||
panel: Node,
|
||||
direction: "left" | "right",
|
||||
direction: "left" | "right" | "up" | "down",
|
||||
callback?: Function
|
||||
) {
|
||||
if (!panel || !panel.isValid) {
|
||||
@@ -526,14 +760,23 @@ export class NavigationManager {
|
||||
|
||||
panel.active = true;
|
||||
|
||||
if (direction === "right") {
|
||||
UITransitionHelper.slideInFromRight(panel, 0.3, () => {
|
||||
callback && callback();
|
||||
});
|
||||
} else {
|
||||
UITransitionHelper.slideInFromLeft(panel, 0.3, () => {
|
||||
callback && callback();
|
||||
});
|
||||
switch (direction) {
|
||||
case "left":
|
||||
UITransitionHelper.slideInFromLeft(panel, 0.3, callback);
|
||||
break;
|
||||
case "right":
|
||||
UITransitionHelper.slideInFromRight(panel, 0.3, callback);
|
||||
break;
|
||||
case "up":
|
||||
UITransitionHelper.slideInFromTop(panel, 0.3, callback);
|
||||
break;
|
||||
case "down":
|
||||
UITransitionHelper.slideInFromBottom(panel, 0.3, callback);
|
||||
break;
|
||||
default:
|
||||
// 默认从右侧滑入
|
||||
UITransitionHelper.slideInFromRight(panel, 0.3, callback);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -544,6 +787,13 @@ export class NavigationManager {
|
||||
return this.currentActivePanelType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前激活的面板节点
|
||||
*/
|
||||
public getCurrentActivePanelNode(): Node {
|
||||
return this.currentActivePanel;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置选中的角色ID
|
||||
* @param girlId 角色ID
|
||||
|
||||
@@ -267,8 +267,6 @@ export class ChatPanel extends li_BaseView implements IChatPanelCallback {
|
||||
// this.videoLayer.playVideo(currentVideo, { size, position });
|
||||
}
|
||||
onChatCountChange() {
|
||||
if (NavigationManager.Instance.getCurrentActivePanel() != PanelType.CHAT)
|
||||
return;
|
||||
console.log("Trigger On ChatCount Change");
|
||||
const girlData = DataManager.I.getDataById<GirlData>(DataId.Girl);
|
||||
let triggerId = girlData.getTriggerGrilPhotoId(this.categoryId, this.id);
|
||||
|
||||
@@ -132,7 +132,6 @@ export class GirlDetailPanel extends li_BaseView {
|
||||
return new Size(600, 800);
|
||||
}
|
||||
|
||||
|
||||
nameKey: string;
|
||||
tagKey: string;
|
||||
descKey: string;
|
||||
@@ -312,7 +311,17 @@ export class GirlDetailPanel extends li_BaseView {
|
||||
|
||||
OnClickChatBtn() {
|
||||
// 使用带过渡动画的导航方法
|
||||
NavigationManager.Instance.switchToPanel(PanelType.CHAT);
|
||||
NavigationManager.Instance.switchToPanel(PanelType.PAST_GIRL_LIST);
|
||||
|
||||
// 延迟打开 ChatPanel,确保 PastGirlListPanel 已经完全加载
|
||||
this.scheduleOnce(() => {
|
||||
// 获取当前活动的 PastGirlListPanel 节点
|
||||
const baseNode = NavigationManager.Instance.getCurrentActivePanelNode();
|
||||
if (baseNode) {
|
||||
const chatData = { girlId: this.id };
|
||||
NavigationManager.Instance.openSubPanel("ChatPanel", baseNode, chatData);
|
||||
}
|
||||
}, 0.5); // 延迟 0.5 秒,确保动画完成
|
||||
}
|
||||
|
||||
returnBtn() {
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
import { _decorator, Node, tween, Vec3, UITransform, view } from "cc";
|
||||
import {
|
||||
_decorator,
|
||||
Node,
|
||||
tween,
|
||||
Vec3,
|
||||
UITransform,
|
||||
view,
|
||||
UIOpacity,
|
||||
} from "cc";
|
||||
|
||||
const { ccclass, property } = _decorator;
|
||||
|
||||
@@ -176,6 +184,322 @@ export class UITransitionHelper {
|
||||
.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 让节点从顶部滑入到屏幕中心
|
||||
*
|
||||
* @param {Node} node - 要执行动画的节点
|
||||
* @param {number} duration - 动画持续时间(秒),默认0.3秒
|
||||
* @param {Function} callback - 动画完成后的回调函数
|
||||
*/
|
||||
public static slideInFromTop(
|
||||
node: Node,
|
||||
duration: number = 0.3,
|
||||
callback?: Function
|
||||
): void {
|
||||
if (!node || !node.isValid) {
|
||||
console.warn("UITransitionHelper: Invalid node for slideInFromTop");
|
||||
return;
|
||||
}
|
||||
|
||||
const screenHeight = view.getVisibleSize().height;
|
||||
const targetPosition = new Vec3(0, 0, 0);
|
||||
|
||||
// 设置初始位置为屏幕顶部外
|
||||
node.setPosition(0, screenHeight, 0);
|
||||
|
||||
// 执行滑入动画到屏幕中心
|
||||
tween(node)
|
||||
.to(
|
||||
duration,
|
||||
{ position: targetPosition },
|
||||
{
|
||||
easing: "cubicOut",
|
||||
}
|
||||
)
|
||||
.call(() => {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 让节点向顶部滑出到屏幕外
|
||||
*
|
||||
* @param {Node} node - 要执行动画的节点
|
||||
* @param {number} duration - 动画持续时间(秒),默认0.3秒
|
||||
* @param {Function} callback - 动画完成后的回调函数
|
||||
*/
|
||||
public static slideOutToTop(
|
||||
node: Node,
|
||||
duration: number = 0.3,
|
||||
callback?: Function
|
||||
): void {
|
||||
if (!node || !node.isValid) {
|
||||
console.warn("UITransitionHelper: Invalid node for slideOutToTop");
|
||||
return;
|
||||
}
|
||||
|
||||
const screenHeight = view.getVisibleSize().height;
|
||||
const currentPosition = node.getPosition();
|
||||
const targetPosition = new Vec3(
|
||||
currentPosition.x,
|
||||
screenHeight,
|
||||
currentPosition.z
|
||||
);
|
||||
|
||||
// 执行滑出动画
|
||||
tween(node)
|
||||
.to(
|
||||
duration,
|
||||
{ position: targetPosition },
|
||||
{
|
||||
easing: "cubicOut",
|
||||
}
|
||||
)
|
||||
.call(() => {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 让节点从底部滑入到屏幕中心
|
||||
*
|
||||
* @param {Node} node - 要执行动画的节点
|
||||
* @param {number} duration - 动画持续时间(秒),默认0.3秒
|
||||
* @param {Function} callback - 动画完成后的回调函数
|
||||
*/
|
||||
public static slideInFromBottom(
|
||||
node: Node,
|
||||
duration: number = 0.3,
|
||||
callback?: Function
|
||||
): void {
|
||||
if (!node || !node.isValid) {
|
||||
console.warn("UITransitionHelper: Invalid node for slideInFromBottom");
|
||||
return;
|
||||
}
|
||||
|
||||
const screenHeight = view.getVisibleSize().height;
|
||||
const targetPosition = new Vec3(0, 0, 0);
|
||||
|
||||
// 设置初始位置为屏幕底部外
|
||||
node.setPosition(0, -screenHeight, 0);
|
||||
|
||||
// 执行滑入动画到屏幕中心
|
||||
tween(node)
|
||||
.to(
|
||||
duration,
|
||||
{ position: targetPosition },
|
||||
{
|
||||
easing: "cubicOut",
|
||||
}
|
||||
)
|
||||
.call(() => {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 让节点向底部滑出到屏幕外
|
||||
*
|
||||
* @param {Node} node - 要执行动画的节点
|
||||
* @param {number} duration - 动画持续时间(秒),默认0.3秒
|
||||
* @param {Function} callback - 动画完成后的回调函数
|
||||
*/
|
||||
public static slideOutToBottom(
|
||||
node: Node,
|
||||
duration: number = 0.3,
|
||||
callback?: Function
|
||||
): void {
|
||||
if (!node || !node.isValid) {
|
||||
console.warn("UITransitionHelper: Invalid node for slideOutToBottom");
|
||||
return;
|
||||
}
|
||||
|
||||
const screenHeight = view.getVisibleSize().height;
|
||||
const currentPosition = node.getPosition();
|
||||
const targetPosition = new Vec3(
|
||||
currentPosition.x,
|
||||
-screenHeight,
|
||||
currentPosition.z
|
||||
);
|
||||
|
||||
// 执行滑出动画
|
||||
tween(node)
|
||||
.to(
|
||||
duration,
|
||||
{ position: targetPosition },
|
||||
{
|
||||
easing: "cubicOut",
|
||||
}
|
||||
)
|
||||
.call(() => {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 淡入效果
|
||||
*
|
||||
* @param {Node} node - 要执行动画的节点
|
||||
* @param {number} duration - 动画持续时间(秒),默认0.3秒
|
||||
* @param {Function} callback - 动画完成后的回调函数
|
||||
*/
|
||||
public static fadeIn(
|
||||
node: Node,
|
||||
duration: number = 0.3,
|
||||
callback?: Function
|
||||
): void {
|
||||
if (!node || !node.isValid) {
|
||||
console.warn("UITransitionHelper: Invalid node for fadeIn");
|
||||
return;
|
||||
}
|
||||
|
||||
let opacity = node.getComponent(UIOpacity);
|
||||
if (!opacity) {
|
||||
opacity = node.addComponent(UIOpacity);
|
||||
}
|
||||
// 设置初始透明度为0
|
||||
opacity.opacity = 0;
|
||||
|
||||
// 执行淡入动画
|
||||
tween(opacity)
|
||||
.to(
|
||||
duration,
|
||||
{ opacity: 255 },
|
||||
{
|
||||
easing: "sineOut",
|
||||
}
|
||||
)
|
||||
.call(() => {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 淡出效果
|
||||
*
|
||||
* @param {Node} node - 要执行动画的节点
|
||||
* @param {number} duration - 动画持续时间(秒),默认0.3秒
|
||||
* @param {Function} callback - 动画完成后的回调函数
|
||||
*/
|
||||
public static fadeOut(
|
||||
node: Node,
|
||||
duration: number = 0.3,
|
||||
callback?: Function
|
||||
): void {
|
||||
if (!node || !node.isValid) {
|
||||
console.warn("UITransitionHelper: Invalid node for fadeOut");
|
||||
return;
|
||||
}
|
||||
|
||||
let opacity = node.getComponent(UIOpacity);
|
||||
if (!opacity) {
|
||||
opacity = node.addComponent(UIOpacity);
|
||||
}
|
||||
// 执行淡出动画
|
||||
tween(opacity)
|
||||
.to(
|
||||
duration,
|
||||
{ opacity: 0 },
|
||||
{
|
||||
easing: "sineOut",
|
||||
}
|
||||
)
|
||||
.call(() => {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 缩放进入效果
|
||||
*
|
||||
* @param {Node} node - 要执行动画的节点
|
||||
* @param {number} duration - 动画持续时间(秒),默认0.3秒
|
||||
* @param {Function} callback - 动画完成后的回调函数
|
||||
*/
|
||||
public static scaleIn(
|
||||
node: Node,
|
||||
duration: number = 0.3,
|
||||
callback?: Function
|
||||
): void {
|
||||
if (!node || !node.isValid) {
|
||||
console.warn("UITransitionHelper: Invalid node for scaleIn");
|
||||
return;
|
||||
}
|
||||
|
||||
// 设置初始缩放为0
|
||||
node.setScale(0, 0, 1);
|
||||
|
||||
// 执行缩放进入动画
|
||||
tween(node)
|
||||
.parallel(
|
||||
tween().to(
|
||||
duration,
|
||||
{ scale: new Vec3(1, 1, 1) },
|
||||
{ easing: "backOut" }
|
||||
),
|
||||
tween().to(duration * 0.8, { opacity: 255 }, { easing: "sineOut" })
|
||||
)
|
||||
.call(() => {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 缩放退出效果
|
||||
*
|
||||
* @param {Node} node - 要执行动画的节点
|
||||
* @param {number} duration - 动画持续时间(秒),默认0.3秒
|
||||
* @param {Function} callback - 动画完成后的回调函数
|
||||
*/
|
||||
public static scaleOut(
|
||||
node: Node,
|
||||
duration: number = 0.3,
|
||||
callback?: Function
|
||||
): void {
|
||||
if (!node || !node.isValid) {
|
||||
console.warn("UITransitionHelper: Invalid node for scaleOut");
|
||||
return;
|
||||
}
|
||||
|
||||
// 执行缩放退出动画
|
||||
tween(node)
|
||||
.parallel(
|
||||
tween().to(
|
||||
duration,
|
||||
{ scale: new Vec3(0, 0, 1) },
|
||||
{ easing: "backIn" }
|
||||
),
|
||||
tween().to(duration * 0.6, { opacity: 0 }, { easing: "sineOut" })
|
||||
)
|
||||
.call(() => {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
})
|
||||
.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止节点上的所有动画
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user