forked from 77media/video-flow
微调空页面动画
This commit is contained in:
parent
80080f97c1
commit
c83f5a4a7e
@ -586,10 +586,9 @@ const ImageQueue = ({ shouldStart, onComplete }: { shouldStart: boolean; onCompl
|
||||
const containers = Array.from(imagesRef.current.children) as HTMLElement[];
|
||||
const videos = containers.map(container => container.querySelector('video')).filter(Boolean) as HTMLVideoElement[];
|
||||
|
||||
if (videos.length > 0) {
|
||||
const finalVideoContainer = document.getElementById('final-video-container') as HTMLDivElement;
|
||||
if (videos.length > 0 && finalVideoContainer) {
|
||||
// 创建最终的大视频容器
|
||||
const finalVideoContainer = document.createElement('div');
|
||||
finalVideoContainer.className = 'fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] rounded-lg overflow-hidden shadow-2xl opacity-0';
|
||||
|
||||
const finalVideo = document.createElement('video');
|
||||
finalVideo.src = finalVideoUrl;
|
||||
@ -600,7 +599,6 @@ const ImageQueue = ({ shouldStart, onComplete }: { shouldStart: boolean; onCompl
|
||||
finalVideo.className = 'w-full h-full object-cover';
|
||||
|
||||
finalVideoContainer.appendChild(finalVideo);
|
||||
document.body.appendChild(finalVideoContainer);
|
||||
finalVideoContainerRef.current = finalVideoContainer;
|
||||
|
||||
// 等待最终视频准备就绪
|
||||
@ -821,7 +819,7 @@ const ImageQueue = ({ shouldStart, onComplete }: { shouldStart: boolean; onCompl
|
||||
};
|
||||
|
||||
// 主要的空状态动画组件
|
||||
export const EmptyStateAnimation = () => {
|
||||
export const EmptyStateAnimation = ({className}: {className: string}) => {
|
||||
const [showText, setShowText] = useState(false);
|
||||
const [showImages, setShowImages] = useState(false);
|
||||
const [animationCycle, setAnimationCycle] = useState(0);
|
||||
@ -829,21 +827,40 @@ export const EmptyStateAnimation = () => {
|
||||
|
||||
// 全局清理函数
|
||||
const globalCleanup = () => {
|
||||
// 清理所有可能的最终视频容器
|
||||
const existingFinalVideos = document.querySelectorAll('div[class*="fixed"][class*="top-1/2"][class*="w-[400px]"]');
|
||||
existingFinalVideos.forEach(container => {
|
||||
if (container.parentNode === document.body) {
|
||||
container.remove();
|
||||
// 清理最终视频容器中的视频元素
|
||||
const finalVideoContainer = document.getElementById('final-video-container') as HTMLDivElement;
|
||||
if (finalVideoContainer) {
|
||||
const finalVideo = finalVideoContainer.querySelector('video');
|
||||
if (finalVideo) {
|
||||
finalVideo.remove();
|
||||
}
|
||||
// 重置容器透明度
|
||||
finalVideoContainer.style.opacity = '0';
|
||||
}
|
||||
|
||||
// 清理所有图片容器中的视频元素
|
||||
const allVideoElements = document.querySelectorAll('video');
|
||||
allVideoElements.forEach(video => {
|
||||
// 确保视频不是在final-video-container中(已经处理过了)
|
||||
if (!finalVideoContainer?.contains(video)) {
|
||||
// 停止播放并移除
|
||||
video.pause();
|
||||
video.removeAttribute('src');
|
||||
video.load(); // 释放资源
|
||||
video.remove();
|
||||
}
|
||||
});
|
||||
|
||||
// 清理所有body下的视频相关元素
|
||||
const bodyChildren = Array.from(document.body.children);
|
||||
bodyChildren.forEach(child => {
|
||||
if (child instanceof HTMLElement &&
|
||||
(child.querySelector('video') || child.tagName === 'VIDEO')) {
|
||||
child.remove();
|
||||
}
|
||||
|
||||
// 清理任何可能遗留的视频容器
|
||||
const imageContainers = document.querySelectorAll('[class*="w-[200px]"][class*="h-[150px]"]');
|
||||
imageContainers.forEach(container => {
|
||||
const videos = container.querySelectorAll('video');
|
||||
videos.forEach(video => {
|
||||
video.pause();
|
||||
video.removeAttribute('src');
|
||||
video.load();
|
||||
video.remove();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -899,7 +916,7 @@ export const EmptyStateAnimation = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex flex-col justify-center items-center'>
|
||||
<div className={`${className} flex flex-col justify-center items-center`}>
|
||||
{showText && (
|
||||
<AnimatedText
|
||||
key={`text-${animationCycle}`}
|
||||
@ -915,6 +932,8 @@ export const EmptyStateAnimation = () => {
|
||||
onComplete={handleImagesComplete}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div id="final-video-container" className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] rounded-lg overflow-hidden shadow-2xl opacity-0"></div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -79,7 +79,17 @@ export function CreateToVideo2() {
|
||||
const [episodeId, setEpisodeId] = useState<number>(0);
|
||||
const [isCreating, setIsCreating] = useState(false);
|
||||
const [generatedVideoList, setGeneratedVideoList] = useState<any[]>([]);
|
||||
const [projectName, setProjectName] = useState(localStorage.getItem('projectName') || '默认名称');
|
||||
const [projectName, setProjectName] = useState('默认名称');
|
||||
|
||||
// 在客户端挂载后读取localStorage
|
||||
useEffect(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const savedProjectName = localStorage.getItem('projectName');
|
||||
if (savedProjectName) {
|
||||
setProjectName(savedProjectName);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleUploadVideo = async () => {
|
||||
console.log('upload video');
|
||||
@ -344,15 +354,19 @@ export function CreateToVideo2() {
|
||||
if (status === 'finished' || status === 'skipped') {
|
||||
setRunTour(false);
|
||||
// 可以在这里存储用户已完成引导的状态
|
||||
localStorage.setItem('hasCompletedTour', 'true');
|
||||
if (typeof window !== 'undefined') {
|
||||
localStorage.setItem('hasCompletedTour', 'true');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 检查是否需要显示引导
|
||||
useEffect(() => {
|
||||
const hasCompletedTour = localStorage.getItem('hasCompletedTour');
|
||||
if (hasCompletedTour) {
|
||||
setRunTour(false);
|
||||
if (typeof window !== 'undefined') {
|
||||
const hasCompletedTour = localStorage.getItem('hasCompletedTour');
|
||||
if (hasCompletedTour) {
|
||||
setRunTour(false);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
@ -363,8 +377,7 @@ export function CreateToVideo2() {
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="container mx-auto overflow-hidden custom-scrollbar"
|
||||
style={isExpanded ? { height: 'calc(100vh - 12rem)' } : { height: 'calc(100vh - 20rem)' }}
|
||||
className="container mx-auto overflow-hidden custom-scrollbar h-[calc(100vh-10rem)]"
|
||||
>
|
||||
{isClient && (
|
||||
<JoyrideNoSSR
|
||||
@ -398,10 +411,10 @@ export function CreateToVideo2() {
|
||||
)}
|
||||
<div className='min-h-[100%] flex flex-col justify-center items-center'>
|
||||
{/* 空状态 */}
|
||||
<EmptyStateAnimation />
|
||||
<EmptyStateAnimation className='h-[calc(100vh - 20rem)]' />
|
||||
{/* 工具栏 */}
|
||||
<div className='video-tool-component relative w-[1080px]'>
|
||||
<div className='video-storyboard-tools grid gap-4 rounded-[20px] bg-[#0C0E11] backdrop-blur-[15px]'>
|
||||
<div className='video-storyboard-tools grid gap-4 rounded-[20px] bg-white/[0.08] backdrop-blur-[20px] border border-white/[0.12] shadow-[0_8px_32px_rgba(0,0,0,0.3)]'>
|
||||
{isExpanded ? (
|
||||
<div className='absolute top-0 bottom-0 left-0 right-0 z-[1] grid justify-items-center place-content-center rounded-[20px] bg-[#191B1E] bg-opacity-[0.3] backdrop-blur-[1.5px] cursor-pointer' onClick={() => setIsExpanded(false)}>
|
||||
{/* 图标 展开按钮 */}
|
||||
|
||||
@ -246,7 +246,7 @@ export function useWorkflowData() {
|
||||
setIsLoading(true);
|
||||
setCurrentLoadingText('正在初始化工作流...');
|
||||
|
||||
const taskId = localStorage.getItem("taskId") || "taskId-123";
|
||||
const taskId = (typeof window !== 'undefined' ? localStorage.getItem("taskId") : null) || "taskId-123";
|
||||
|
||||
// 首先加载数据
|
||||
await loadMockData();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user