Files
carrotskin/src/app/page.tsx

308 lines
13 KiB
TypeScript
Raw Normal View History

'use client';
import { useState, useEffect } from 'react';
import Link from 'next/link';
import { motion, useScroll, useTransform } from 'framer-motion';
import {
ArrowRightIcon,
ShieldCheckIcon,
CloudArrowUpIcon,
ShareIcon,
CubeIcon,
UserGroupIcon,
SparklesIcon,
RocketLaunchIcon
} from '@heroicons/react/24/outline';
2025-12-04 10:17:03 +08:00
export default function Home() {
const { scrollYProgress } = useScroll();
const opacity = useTransform(scrollYProgress, [0, 0.3], [1, 0]);
const scale = useTransform(scrollYProgress, [0, 0.3], [1, 0.8]);
const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 });
const [isHovered, setIsHovered] = useState(false);
useEffect(() => {
const handleMouseMove = (e: MouseEvent) => {
setMousePosition({ x: e.clientX, y: e.clientY });
};
window.addEventListener('mousemove', handleMouseMove);
return () => {
window.removeEventListener('mousemove', handleMouseMove);
};
}, []);
const features = [
{
icon: ShieldCheckIcon,
title: "Yggdrasil认证",
description: "完整的Minecraft Yggdrasil API支持安全可靠的用户认证系统",
color: "from-amber-400 to-orange-500"
},
{
icon: CloudArrowUpIcon,
title: "云端存储",
description: "无限皮肤存储空间,自动备份,随时随地访问你的皮肤库",
color: "from-orange-400 to-red-500"
},
{
icon: ShareIcon,
title: "社区分享",
description: "与全球玩家分享创作,发现灵感,建立你的粉丝群体",
color: "from-red-400 to-pink-500"
},
{
icon: CubeIcon,
title: "3D预览",
description: "实时3D皮肤预览360度旋转查看支持多种渲染模式",
color: "from-pink-400 to-purple-500"
}
];
const stats = [
{ number: "50K+", label: "注册用户" },
{ number: "200K+", label: "皮肤上传" },
{ number: "1M+", label: "月活用户" },
{ number: "99.9%", label: "服务可用性" }
];
2025-12-04 10:17:03 +08:00
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 via-orange-50 to-amber-50 dark:from-gray-900 dark:via-gray-800 dark:to-gray-900">
{/* Animated Background */}
<div className="fixed inset-0 overflow-hidden pointer-events-none">
<div className="absolute -top-40 -right-40 w-80 h-80 bg-gradient-to-br from-orange-400/20 to-amber-400/20 rounded-full blur-3xl animate-pulse"></div>
<div className="absolute -bottom-40 -left-40 w-80 h-80 bg-gradient-to-tr from-pink-400/20 to-orange-400/20 rounded-full blur-3xl animate-pulse delay-1000"></div>
<div
className="absolute w-32 h-32 bg-gradient-to-r from-orange-400/30 to-amber-400/30 rounded-full blur-2xl transition-all duration-150 ease-out will-change-transform"
style={{
transform: `translate(${mousePosition.x - 64}px, ${mousePosition.y - 64}px) scale(${isHovered ? 1.5 : 1})`
}}
2025-12-04 10:17:03 +08:00
/>
</div>
{/* Hero Section */}
<motion.section
style={{ opacity, scale }}
className="relative min-h-screen flex items-center justify-center px-4 sm:px-6 lg:px-8 overflow-hidden"
>
<div className="relative z-10 max-w-7xl mx-auto text-center">
<motion.div
initial={{ opacity: 0, y: 30 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, ease: "easeOut" }}
>
{/* Logo Animation */}
<motion.div
className="mb-8 flex justify-center"
initial={{ scale: 0, rotate: -180 }}
animate={{ scale: 1, rotate: 0 }}
transition={{ duration: 1, type: "spring", stiffness: 100 }}
2025-12-04 10:17:03 +08:00
>
<div className="relative">
<div className="w-24 h-24 bg-gradient-to-br from-orange-400 via-amber-500 to-orange-600 rounded-3xl flex items-center justify-center shadow-2xl">
<span className="text-4xl font-bold text-white">CS</span>
</div>
<motion.div
className="absolute -inset-2 bg-gradient-to-br from-orange-400/30 to-amber-500/30 rounded-3xl blur-lg"
animate={{ scale: [1, 1.1, 1] }}
transition={{ duration: 2, repeat: Infinity }}
/>
</div>
</motion.div>
<h1 className="text-6xl md:text-8xl font-black text-gray-900 dark:text-white mb-6 tracking-tight">
<span className="bg-gradient-to-r from-orange-500 via-amber-500 to-orange-600 bg-clip-text text-transparent">
CarrotSkin
</span>
</h1>
<motion.p
className="text-xl md:text-2xl text-gray-600 dark:text-gray-300 mb-8 max-w-3xl mx-auto font-light leading-relaxed"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.3, duration: 0.6 }}
2025-12-04 10:17:03 +08:00
>
<span className="font-semibold text-orange-500">Minecraft Yggdrasil</span>
<br className="hidden sm:block" />
</motion.p>
<motion.div
className="flex flex-col sm:flex-row gap-4 justify-center items-center"
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: 0.5, duration: 0.6 }}
>
<Link
href="/register"
className="group relative overflow-hidden bg-gradient-to-r from-orange-500 to-amber-500 text-white font-semibold py-4 px-8 rounded-2xl transition-all duration-300 hover:shadow-2xl hover:shadow-orange-500/25"
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<span className="relative z-10 flex items-center space-x-2">
<span></span>
<ArrowRightIcon className="w-5 h-5 group-hover:translate-x-1 transition-transform" />
</span>
<motion.div
className="absolute inset-0 bg-gradient-to-r from-amber-500 to-orange-500"
initial={{ x: '-100%' }}
whileHover={{ x: 0 }}
transition={{ duration: 0.3 }}
/>
</Link>
<Link
href="/skins"
className="group border-2 border-orange-200 dark:border-orange-700 text-orange-600 dark:text-orange-400 font-semibold py-4 px-8 rounded-2xl transition-all duration-300 hover:bg-orange-500 hover:text-white hover:border-orange-500"
>
<span className="flex items-center space-x-2">
<span></span>
<SparklesIcon className="w-5 h-5 group-hover:rotate-12 transition-transform" />
</span>
</Link>
</motion.div>
</motion.div>
2025-12-04 10:17:03 +08:00
</div>
{/* Scroll Indicator */}
<motion.div
className="absolute bottom-12 left-1/2 transform -translate-x-1/2"
animate={{ y: [0, 10, 0] }}
transition={{ duration: 2, repeat: Infinity }}
>
<div className="w-6 h-10 border-2 border-orange-400 rounded-full flex justify-center">
<motion.div
className="w-1 h-3 bg-orange-400 rounded-full mt-2"
animate={{ y: [0, 16, 0] }}
transition={{ duration: 2, repeat: Infinity }}
2025-12-04 10:17:03 +08:00
/>
</div>
</motion.div>
</motion.section>
{/* Stats Section */}
<section className="py-20 px-4 sm:px-6 lg:px-8">
<div className="max-w-7xl mx-auto">
<div className="grid grid-cols-2 lg:grid-cols-4 gap-8">
{stats.map((stat, index) => (
<motion.div
key={index}
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1, duration: 0.6 }}
viewport={{ once: true }}
className="text-center group"
>
<div className="text-4xl md:text-5xl font-black bg-gradient-to-r from-orange-500 to-amber-500 bg-clip-text text-transparent mb-2">
{stat.number}
</div>
<div className="text-gray-600 dark:text-gray-400 font-medium">
{stat.label}
</div>
<div className="h-1 w-16 bg-gradient-to-r from-orange-400 to-amber-400 mx-auto mt-3 rounded-full group-hover:w-24 transition-all duration-300"></div>
</motion.div>
))}
</div>
</div>
</section>
{/* Features Section */}
<section className="py-20 px-4 sm:px-6 lg:px-8 relative">
<div className="max-w-7xl mx-auto">
<motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
viewport={{ once: true }}
className="text-center mb-16"
2025-12-04 10:17:03 +08:00
>
<h2 className="text-4xl md:text-5xl font-black text-gray-900 dark:text-white mb-6">
<span className="bg-gradient-to-r from-orange-500 to-amber-500 bg-clip-text text-transparent"> </span>
</h2>
<p className="text-xl text-gray-600 dark:text-gray-400 max-w-3xl mx-auto font-light">
</p>
</motion.div>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{features.map((feature, index) => (
<motion.div
key={index}
initial={{ opacity: 0, x: index % 2 === 0 ? -50 : 50 }}
whileInView={{ opacity: 1, x: 0 }}
transition={{ delay: index * 0.1, duration: 0.6 }}
viewport={{ once: true }}
className="group relative"
>
<div className="bg-white/70 dark:bg-gray-800/70 backdrop-blur-lg rounded-3xl p-8 shadow-xl hover:shadow-2xl transition-all duration-300 border border-white/20 dark:border-gray-700/50">
<div className={`w-16 h-16 bg-gradient-to-br ${feature.color} rounded-2xl flex items-center justify-center mb-6 shadow-lg group-hover:scale-110 transition-transform duration-300`}>
<feature.icon className="w-8 h-8 text-white" />
</div>
<h3 className="text-2xl font-bold text-gray-900 dark:text-white mb-4">
{feature.title}
</h3>
<p className="text-gray-600 dark:text-gray-300 leading-relaxed">
{feature.description}
</p>
</div>
</motion.div>
))}
</div>
2025-12-04 10:17:03 +08:00
</div>
</section>
{/* CTA Section */}
<section className="py-20 px-4 sm:px-6 lg:px-8 relative overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-br from-orange-500 via-amber-500 to-orange-600">
<div className="absolute inset-0 bg-black/10"></div>
</div>
<motion.div
className="relative z-10 max-w-4xl mx-auto text-center"
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8 }}
viewport={{ once: true }}
>
<motion.div
animate={{ rotate: 360 }}
transition={{ duration: 20, repeat: Infinity, ease: "linear" }}
className="w-32 h-32 bg-white/10 rounded-full flex items-center justify-center mx-auto mb-8"
>
<RocketLaunchIcon className="w-16 h-16 text-white/80" />
</motion.div>
<h2 className="text-4xl md:text-5xl font-black text-white mb-6">
</h2>
<p className="text-xl text-white/90 mb-8 max-w-2xl mx-auto font-light">
CarrotSkinMinecraft皮肤管理平台
</p>
<div className="flex flex-col sm:flex-row gap-4 justify-center">
<Link
href="/register"
className="group bg-white text-orange-600 hover:bg-gray-100 font-bold py-4 px-8 rounded-2xl transition-all duration-300 inline-flex items-center space-x-2 shadow-2xl"
>
<span></span>
<ArrowRightIcon className="w-5 h-5 group-hover:translate-x-1 transition-transform" />
</Link>
<Link
href="/api"
className="border-2 border-white/30 text-white hover:bg-white/10 font-bold py-4 px-8 rounded-2xl transition-all duration-300 inline-flex items-center space-x-2"
>
<span>API文档</span>
<UserGroupIcon className="w-5 h-5" />
</Link>
</div>
</motion.div>
</section>
2025-12-04 10:17:03 +08:00
</div>
);
}