forked from 77media/video-flow
522 lines
17 KiB
TypeScript
522 lines
17 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useRef, useEffect, useMemo } from "react";
|
|
import {
|
|
Table,
|
|
AlignHorizontalSpaceAround,
|
|
Loader2,
|
|
Clapperboard,
|
|
CircleArrowRight,
|
|
} from "lucide-react";
|
|
import "./style/home-page2.css";
|
|
import { useRouter } from "next/navigation";
|
|
import { Swiper, SwiperSlide } from "swiper/react";
|
|
import "swiper/swiper-bundle.css"; // 引入样式
|
|
import { Autoplay } from "swiper/modules";
|
|
|
|
import { VideoCarouselLayout } from "@/components/video-carousel-layout";
|
|
import { VideoGridLayout } from "@/components/video-grid-layout";
|
|
import { motion, AnimatePresence } from "framer-motion";
|
|
import { LiquidButton } from "@/components/ui/liquid-glass-button";
|
|
import {
|
|
createScriptProject,
|
|
CreateScriptProjectRequest,
|
|
} from "@/api/script_project";
|
|
import { ProjectTypeEnum, ModeEnum, ResolutionEnum } from "@/app/model/enums";
|
|
import { getResourcesList, Resource } from "@/api/resources";
|
|
import { Carousel } from "antd";
|
|
import { TextCanvas } from "../common/TextCanvas";
|
|
|
|
export function HomePage2() {
|
|
const [hPading, setHPading] = useState(0);
|
|
useEffect(() => {
|
|
setHPading((window as any).Scale.hScale * 11);
|
|
}, []);
|
|
return (
|
|
//
|
|
<div
|
|
className="w-full h-full overflow-y-auto"
|
|
style={{ paddingBottom: `${hPading}rem` }}
|
|
>
|
|
<HomeModule1 />
|
|
<HomeModule2 />
|
|
<HomeModule3 />
|
|
<HomeModule4 />
|
|
<HomeModule5 />
|
|
<HomeModule6 />
|
|
</div>
|
|
);
|
|
}
|
|
|
|
/** 首屏 */
|
|
function HomeModule1() {
|
|
const router = useRouter();
|
|
return (
|
|
<div className="home-module1 relative flex justify-center items-center w-full h-[1280px] bg-black snap-start">
|
|
<video
|
|
src="/assets/home.mp4"
|
|
autoPlay
|
|
loop
|
|
muted
|
|
playsInline
|
|
className="absolute top-0 left-0 z-1 w-full h-full object-cover"
|
|
></video>
|
|
<div className="center z-10 flex flex-col items-center">
|
|
<h1 className="text-white text-[5.75rem] leading-[100%] font-bold mb-[5rem]">
|
|
Ideas Become Movies
|
|
</h1>
|
|
<p className="text-white text-[2rem] leading-[140%] font-normal">
|
|
Next-Generation AI Movies Making Platform
|
|
</p>
|
|
<p className="text-white text-[2rem] leading-[140%] font-normal">
|
|
From Ideas to Movies in just 5-10 minutes
|
|
</p>
|
|
<div
|
|
className="w-[11.5rem] h-[3.75rem] mt-[4rem] text-base flex justify-center items-center font-normal border border-white rounded-full bg-white/30 cursor-pointer"
|
|
onClick={() => router.push("/create")}
|
|
>
|
|
Early Access
|
|
<CircleArrowRight className="ml-[1rem]" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
/**核心价值 */
|
|
function HomeModule2() {
|
|
return (
|
|
<div
|
|
data-alt="core-value-section"
|
|
className="home-module2 relative flex flex-col items-center justify-center w-full h-[1600px] bg-black snap-start"
|
|
>
|
|
<div
|
|
data-alt="core-value-content"
|
|
className="center z-10 flex flex-col items-center mb-[14rem]"
|
|
>
|
|
<h2 className="text-white text-[3.375rem] leading-[100%] font-normal mb-[3rem]">
|
|
Just Give Us Your Ideas
|
|
</h2>
|
|
<p className="text-white text-[1.125rem] leading-[140%] font-normal text-center">
|
|
Input your idea in one sentence and MovieFlow will bring
|
|
</p>
|
|
<p className="text-white text-[1.125rem] leading-[140%] font-normal text-center">
|
|
your creativity to life
|
|
</p>
|
|
</div>
|
|
<div
|
|
data-alt="core-value-video"
|
|
className="relative w-[80rem] h-[45rem] flex justify-center items-center border border-white/20 rounded-lg overflow-hidden"
|
|
>
|
|
<video
|
|
src="/assets/1.mp4"
|
|
autoPlay
|
|
loop
|
|
muted
|
|
playsInline
|
|
className="w-full h-full object-cover"
|
|
></video>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
/**案例展示 */
|
|
function HomeModule3() {
|
|
const videoList = [
|
|
[
|
|
"/assets/show (1).mp4",
|
|
"/assets/show (2).mp4",
|
|
"/assets/show (3).mp4",
|
|
"/assets/show (4).mp4",
|
|
"/assets/show (5).mp4",
|
|
],
|
|
[
|
|
"/assets/show (6).mp4",
|
|
"/assets/show (7).mp4",
|
|
"/assets/show (8).mp4",
|
|
"/assets/show (9).mp4",
|
|
"/assets/show (10).mp4",
|
|
],
|
|
[
|
|
"/assets/show (11).mp4",
|
|
"/assets/show (12).mp4",
|
|
"/assets/show (13).mp4",
|
|
"/assets/show (14).mp4",
|
|
"/assets/show (15).mp4",
|
|
],
|
|
];
|
|
|
|
// 定义内容样式
|
|
const contentStyle: React.CSSProperties = {
|
|
height: "100%",
|
|
lineHeight: "10rem",
|
|
textAlign: "center",
|
|
background: "#364d79",
|
|
};
|
|
|
|
return (
|
|
<div className="home-module3 h-[1666px] relative flex flex-col items-center justify-center w-full bg-black snap-start">
|
|
<div className="center z-10 flex flex-col items-center mb-[14rem]">
|
|
<h2 className="text-white text-[3.375rem] leading-[100%] font-normal mb-[3rem]">
|
|
Create Anything
|
|
</h2>
|
|
<p className="text-white text-[1.125rem] leading-[140%] font-normal text-center">
|
|
MovieFlow can make any kind of film in high quality for you
|
|
</p>
|
|
</div>
|
|
{/* 3x3网格布局 */}
|
|
<div
|
|
data-alt="vertical-grid-shadow"
|
|
className="grid grid-cols-3 gap-[1rem] w-full h-[64rem] px-[5rem] relative"
|
|
>
|
|
{/* 上方阴影遮罩 - 覆盖整个宽度包括padding */}
|
|
<div className="absolute -top-[0.0625rem] -left-0 w-full h-[6rem] bg-gradient-to-b from-black via-black/30 to-transparent z-20 pointer-events-none"></div>
|
|
|
|
{/* 下方阴影遮罩 - 覆盖整个宽度包括padding */}
|
|
<div className="absolute -bottom-[0.0625rem] -left-0 w-full h-[6rem] bg-gradient-to-t from-black via-black/30 to-transparent z-20 pointer-events-none"></div>
|
|
|
|
{videoList.map((column, columnIndex) => (
|
|
<div
|
|
key={columnIndex}
|
|
className="w-[35.5rem] h-[64rem] relative z-10"
|
|
>
|
|
<Swiper
|
|
modules={[Autoplay]}
|
|
direction="vertical"
|
|
loop={true}
|
|
spaceBetween={0}
|
|
slidesPerView={3}
|
|
autoplay={{
|
|
delay: 0,
|
|
pauseOnMouseEnter: true,
|
|
disableOnInteraction: false,
|
|
reverseDirection: columnIndex % 2 === 0,
|
|
}}
|
|
speed={6000}
|
|
grabCursor={true}
|
|
className="w-full h-full"
|
|
cssMode={false}
|
|
freeMode={true}
|
|
watchSlidesProgress={false}
|
|
style={
|
|
{
|
|
"--swiper-wrapper-transition-timing-function": "linear",
|
|
} as React.CSSProperties
|
|
}
|
|
>
|
|
{column.map((video, videoIndex) => (
|
|
<SwiperSlide key={videoIndex}>
|
|
<div className="w-full h-[20rem] bg-gray-800 rounded-2xl overflow-hidden">
|
|
<video
|
|
src={video}
|
|
loop
|
|
muted
|
|
playsInline
|
|
className="w-full h-full object-cover"
|
|
onMouseEnter={(e) => {
|
|
const videoElement = e.currentTarget;
|
|
videoElement.play();
|
|
}}
|
|
/>
|
|
</div>
|
|
</SwiperSlide>
|
|
))}
|
|
</Swiper>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
/**电影制作工序介绍 */
|
|
function HomeModule4() {
|
|
const [activeTab, setActiveTab] = useState(0);
|
|
|
|
const processSteps = [
|
|
{
|
|
title: "Pre-Production",
|
|
description:
|
|
"Developing the story, writing the script, securing funding, assembling the crew, and planning the shoot.",
|
|
},
|
|
{
|
|
title: "Production",
|
|
description:
|
|
"Developing the story, writing the script, securing funding, assembling the crew, and planning the shoot.",
|
|
},
|
|
{
|
|
title: "Visual Effects",
|
|
description:
|
|
"Developing the story, writing the script, securing funding, assembling the crew, and planning the shoot.",
|
|
},
|
|
{
|
|
title: "Voice",
|
|
description:
|
|
"Developing the story, writing the script, securing funding, assembling the crew, and planning the shoot.",
|
|
},
|
|
];
|
|
|
|
const handleTabClick = (index: number) => {
|
|
setActiveTab(index);
|
|
};
|
|
|
|
return (
|
|
<div
|
|
data-alt="core-value-section"
|
|
className="home-module4 h-[1280px] relative flex flex-col items-center justify-center w-full bg-black snap-start"
|
|
>
|
|
<div
|
|
data-alt="core-value-content"
|
|
className="center z-10 flex flex-col items-center mb-[14rem]"
|
|
>
|
|
<h2 className="text-white text-[3.375rem] leading-[100%] font-normal mb-[3rem]">
|
|
Edit like you think
|
|
</h2>
|
|
</div>
|
|
|
|
<div className="flex w-full px-[4rem] gap-[2rem]">
|
|
{/* 左侧四个切换tab */}
|
|
<div className="flex flex-col gap-[1rem]">
|
|
{processSteps.map((step, index) => (
|
|
<div
|
|
key={index}
|
|
onClick={() => handleTabClick(index)}
|
|
className={`w-[31.75rem] h-[10.5rem] rounded-lg cursor-pointer transition-all duration-300 border ${
|
|
activeTab === index
|
|
? "bg-[#262626] border-white/20 hover:border-white/40"
|
|
: "bg-black border-white/10 hover:border-white/40"
|
|
}`}
|
|
>
|
|
<div className="p-[1.5rem] h-full flex flex-col justify-center">
|
|
<h3
|
|
className={`text-[2rem] font-normal mb-[1.5rem] ${
|
|
activeTab === index ? "text-white" : "text-white/70"
|
|
}`}
|
|
>
|
|
{step.title}
|
|
</h3>
|
|
<p
|
|
className={`text-[0.875rem] leading-[140%] ${
|
|
activeTab === index ? "text-white" : "text-white/70"
|
|
}`}
|
|
>
|
|
{step.description}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* 右侧视频播放区域 */}
|
|
<div className="flex-1 flex justify-center">
|
|
<div className="w-[80rem] h-[45rem] bg-gray-800 rounded-lg overflow-hidden border border-white/20">
|
|
<video
|
|
key={activeTab}
|
|
src="/assets/home.mp4"
|
|
autoPlay
|
|
loop
|
|
muted
|
|
playsInline
|
|
className="w-full h-full object-cover"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
/**价格方案 */
|
|
function HomeModule5() {
|
|
const [billingType, setBillingType] = useState<"monthly" | "yearly">(
|
|
"monthly"
|
|
);
|
|
|
|
const pricingPlans = [
|
|
{
|
|
title: "Plus",
|
|
price: billingType === "monthly" ? 28 : 24,
|
|
credits: "1x Boost, 10 Credits",
|
|
buttonText: "Choose Plus",
|
|
features: [
|
|
"10 Credits",
|
|
"50 Video mins + 95 iStock",
|
|
"2 UGC product asset ads",
|
|
"30 secs of generative video",
|
|
"2 express clones",
|
|
"3 users, 100GB storage",
|
|
"Unlimited exports",
|
|
],
|
|
},
|
|
{
|
|
title: "Max",
|
|
price: billingType === "monthly" ? 50 : 43,
|
|
credits: "1x Boost, 40 Credits",
|
|
buttonText: "Choose Max",
|
|
features: [
|
|
"40 Credits",
|
|
"50 Video mins + 95 iStock",
|
|
"2 UGC product asset ads",
|
|
"30 secs of generative video",
|
|
"2 express clones",
|
|
"3 users, 100GB storage",
|
|
"Unlimited exports",
|
|
],
|
|
},
|
|
{
|
|
title: "Generative",
|
|
price: billingType === "monthly" ? 100 : 85,
|
|
credits: "1x Boost, 100 Credits",
|
|
buttonText: "Choose Generative",
|
|
features: [
|
|
"100 Credits",
|
|
"50 Video mins + 95 iStock",
|
|
"2 UGC product asset ads",
|
|
"30 secs of generative video",
|
|
"2 express clones",
|
|
"3 users, 100GB storage",
|
|
"Unlimited exports",
|
|
],
|
|
},
|
|
{
|
|
title: "Team",
|
|
price: billingType === "monthly" ? 899 : 764,
|
|
credits: "1x Boost, 1000 Credits",
|
|
buttonText: "Choose Team",
|
|
features: [
|
|
"1000 Credits",
|
|
"50 Video mins + 95 iStock",
|
|
"2 UGC product asset ads",
|
|
"30 secs of generative video",
|
|
"2 express clones",
|
|
"3 users, 100GB storage",
|
|
"Unlimited exports",
|
|
],
|
|
},
|
|
];
|
|
|
|
return (
|
|
<div
|
|
data-alt="core-value-section"
|
|
className="home-module5 h-[1600px] relative flex flex-col items-center justify-center w-full bg-black snap-start"
|
|
>
|
|
<div
|
|
data-alt="core-value-content"
|
|
className="center z-10 flex flex-col items-center mb-[8rem]"
|
|
>
|
|
<h2 className="text-white text-[3.375rem] leading-[100%] font-normal mb-[1.5rem]">
|
|
Start Creating
|
|
</h2>
|
|
|
|
{/* 计费切换 */}
|
|
<div className="h-[3.375rem] flex bg-black rounded-full p-[0.0625rem] mt-[1.5rem] border border-white/20">
|
|
<button
|
|
onClick={() => setBillingType("monthly")}
|
|
className={`box-border flex justify-center items-center w-[6rem] text-base rounded-full transition-all duration-300 ${
|
|
billingType === "monthly"
|
|
? "bg-white text-black"
|
|
: "text-white hover:text-gray-300"
|
|
}`}
|
|
>
|
|
Monthly
|
|
</button>
|
|
<button
|
|
onClick={() => setBillingType("yearly")}
|
|
className={`box-border flex justify-center items-center w-[7.125rem] text-base rounded-full transition-all duration-300 ${
|
|
billingType === "yearly"
|
|
? "bg-white text-black"
|
|
: "text-white hover:text-gray-300"
|
|
}`}
|
|
>
|
|
Yearly - <span className="text-[#FFCC6D]">15%</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* 主要价格卡片 */}
|
|
<div className="grid grid-cols-4 gap-[1.5rem] w-full px-[12rem] mb-[2rem]">
|
|
{pricingPlans.map((plan, index) => (
|
|
<div
|
|
key={index}
|
|
className=" h-[38.125rem] bg-black rounded-lg p-[1.5rem] border border-white/20"
|
|
>
|
|
<h3 className="text-white text-2xl font-normal mb-[1rem]">
|
|
{plan.title}
|
|
</h3>
|
|
<div className="mb-[1rem]">
|
|
<span className="text-white text-[3.375rem] font-bold">
|
|
${plan.price}
|
|
</span>
|
|
<span className="text-white text-xs ml-[0.5rem]">/month</span>
|
|
</div>
|
|
<p className="text-white text-[0.875rem] mb-[1rem]">
|
|
{plan.credits}
|
|
</p>
|
|
<button className="w-full bg-white text-black py-[0.75rem] rounded-full mb-[1rem] hover:bg-black hover:text-white transition-colors border border-white/20">
|
|
{plan.buttonText}
|
|
</button>
|
|
<p className="w-full text-center text-white/60 text-[0.75rem] mb-[2rem]">
|
|
* Billed monthly until cancelled
|
|
</p>
|
|
<ul className="space-y-[1rem]">
|
|
{plan.features.map((feature, featureIndex) => (
|
|
<li
|
|
key={featureIndex}
|
|
className="flex items-center text-white text-[0.875rem]"
|
|
>
|
|
<span className="text-[#C73BFF] mr-[0.5rem]">✓</span>
|
|
{feature}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* 额外价格卡片 */}
|
|
<div className="flex gap-[1.5rem] w-full px-[12rem]">
|
|
<div className="flex-1 bg-black rounded-lg p-[1.5rem] border border-white/20">
|
|
<h3 className="text-white text-[1.5rem] font-bold mb-[0.5rem]">
|
|
Free
|
|
</h3>
|
|
<div className="mb-[1rem]">
|
|
<span className="text-white text-[2.5rem] font-bold">$0</span>
|
|
</div>
|
|
<p className="text-white text-[0.875rem] mb-[1.5rem] leading-relaxed">
|
|
10 Video mins and 1 AI credit per week, 1 Express avatar, 4 Exports
|
|
per week with invideo watermark.
|
|
</p>
|
|
<p className="text-white text-[0.875rem] mb-[1.5rem] leading-relaxed">
|
|
No access to generative features.
|
|
</p>
|
|
<button className="w-[9rem] bg-[#262626] text-white py-[0.75rem] rounded-full hover:bg-white hover:text-black transition-colors border border-white/20">
|
|
Try For Free
|
|
</button>
|
|
</div>
|
|
|
|
<div className="flex-1 bg-black rounded-lg p-[1.5rem] border border-white/20">
|
|
<h3 className="text-white text-[1.5rem] font-bold mb-[0.5rem]">
|
|
Enterprise
|
|
</h3>
|
|
<p className="text-white text-[2.5rem] mb-[1rem]">Custom</p>
|
|
<p className="text-white text-[0.875rem] mb-[1.5rem] leading-relaxed">
|
|
Custom solutions for large organizations. Advanced security and
|
|
flexible pricing based on your needs.
|
|
</p>
|
|
<p className="text-white text-[0.875rem] mb-[1.5rem] leading-relaxed">
|
|
on your needs.
|
|
</p>
|
|
<button className="w-[9rem] bg-[#262626] text-white py-[0.75rem] rounded-full hover:bg-white hover:text-black transition-colors border border-white/20">
|
|
Contact Us
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function HomeModule6() {
|
|
return (
|
|
<div className="home-module6 flex justify-center items-center w-full h-min text-white/50 text-lg bg-black snap-start">
|
|
© 2025 MovieFlow. All rights reserved.
|
|
</div>
|
|
);
|
|
}
|