This commit is contained in:
2025-09-21 13:05:43 +08:00
parent 7722ccf694
commit 69937cf669
7 changed files with 616 additions and 36 deletions
@@ -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