You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
AdLike2048/assets/mx/module/ui/popAnim/PopAnimReveal.ts

80 lines
2.6 KiB

import { Node, Vec3 } from 'cc';
import { IPopRevealConfig } from './PopAnimTypes';
import { popStaggerNode } from './PopAnimStagger';
const ITEM_GAP = 0.04;
const ITEM_DUR = 0.22;
const LAST_GAP = 0.05;
/** 在 root / ui_center 下查找节点 */
export function resolvePopNode(root: Node, center: Node | null, name: string): Node | null {
if (!name) return null;
if (center?.getChildByName(name)) return center.getChildByName(name);
if (root.getChildByName(name)) return root.getChildByName(name);
if (center) {
for (const c of center.children) {
const n = c.getChildByName(name);
if (n) return n;
}
}
return null;
}
function collectItemNodes(root: Node, center: Node | null, cfg: IPopRevealConfig): Node[] {
const out: Node[] = [];
if (cfg.itemsNode) {
const container = resolvePopNode(root, center, cfg.itemsNode);
if (container?.isValid) {
for (const c of container.children) {
if (c.active) out.push(c);
}
}
}
if (cfg.itemNodes) {
for (const name of cfg.itemNodes) {
const n = resolvePopNode(root, center, name);
if (n?.isValid && n.active) out.push(n);
}
}
return out;
}
function hideNode(node: Node): void {
node.setScale(Vec3.ZERO);
}
/** 上屏前:列表项与尾部按钮默认隐藏 */
export function preparePopReveal(root: Node, center: Node | null, cfg: IPopRevealConfig): void {
for (const n of collectItemNodes(root, center, cfg)) {
hideNode(n);
}
for (const name of cfg.lastNodes ?? []) {
const n = resolvePopNode(root, center, name);
if (n?.isValid && n.active) hideNode(n);
}
}
/** 内容区入场完成后:分帧错峰出现 */
export function runPopReveal(root: Node, center: Node | null, cfg: IPopRevealConfig): void {
const itemPreset = cfg.itemsPreset ?? 'scale';
const lastPreset = cfg.lastPreset ?? 'scale';
const items = collectItemNodes(root, center, cfg);
items.forEach((n, i) => {
popStaggerNode(n, itemPreset, i * ITEM_GAP);
});
const lastStart = items.length * ITEM_GAP + ITEM_DUR * 0.55;
(cfg.lastNodes ?? []).forEach((name, i) => {
const n = resolvePopNode(root, center, name);
if (n?.isValid && n.active) {
popStaggerNode(n, lastPreset, lastStart + i * LAST_GAP);
}
});
}
export function estimateRevealDuration(cfg: IPopRevealConfig): number {
const itemCount = (cfg.itemNodes?.length ?? 0) + (cfg.itemsNode ? 1 : 0);
const lastCount = cfg.lastNodes?.length ?? 0;
return itemCount * ITEM_GAP + ITEM_DUR + lastCount * LAST_GAP;
}