77 lines
2.1 KiB
TypeScript
77 lines
2.1 KiB
TypeScript
import React, { useEffect, useState } from 'react';
|
|
import { CSSTransition, TransitionGroup } from 'react-transition-group';
|
|
import { useLocation } from 'umi';
|
|
import './index.less';
|
|
|
|
export interface PageTransitionProps {
|
|
children: React.ReactNode;
|
|
type?: 'fade' | 'slide' | 'scale';
|
|
duration?: number;
|
|
className?: string;
|
|
}
|
|
|
|
const PageTransition: React.FC<PageTransitionProps> = ({
|
|
children,
|
|
type = 'fade',
|
|
duration = 300,
|
|
className = '',
|
|
}) => {
|
|
const location = useLocation();
|
|
const [displayLocation, setDisplayLocation] = useState(location);
|
|
const [transitionStage, setTransitionStage] = useState('fadeIn');
|
|
|
|
useEffect(() => {
|
|
if (location !== displayLocation) setTransitionStage('fadeOut');
|
|
}, [location, displayLocation]);
|
|
|
|
return (
|
|
<div className={`page-transition ${type}-transition ${className}`}>
|
|
<div
|
|
className={`transition-content ${transitionStage}`}
|
|
onAnimationEnd={() => {
|
|
if (transitionStage === 'fadeOut') {
|
|
setDisplayLocation(location);
|
|
setTransitionStage('fadeIn');
|
|
}
|
|
}}
|
|
>
|
|
{children}
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
// 简化版本 - 禁用所有动画
|
|
export const SimplePageTransition: React.FC<{
|
|
children: React.ReactNode;
|
|
className?: string;
|
|
enableAnimation?: boolean;
|
|
onAnimationEnd?: () => void;
|
|
}> = ({
|
|
children,
|
|
className = '',
|
|
enableAnimation = false, // 强制禁用动画
|
|
onAnimationEnd,
|
|
}) => {
|
|
// 立即执行回调,不等待动画
|
|
const handleAnimationEnd = () => {
|
|
if (onAnimationEnd) {
|
|
onAnimationEnd();
|
|
}
|
|
};
|
|
|
|
// 立即执行动画结束回调
|
|
React.useEffect(() => {
|
|
if (onAnimationEnd) {
|
|
onAnimationEnd();
|
|
}
|
|
}, [onAnimationEnd]);
|
|
|
|
return (
|
|
<div className={`simple-page-transition ${className}`}>
|
|
{children}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default PageTransition; |