Skip to content

Commit e25385d

Browse files
committed
feat: 优化Hero组件,移除图片预加载,优化选择器
1 parent 8920c88 commit e25385d

File tree

1 file changed

+18
-76
lines changed

1 file changed

+18
-76
lines changed

app/components/home/Hero.tsx

Lines changed: 18 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,11 @@ import { buttonVariants } from 'app/components/ui/button';
1414
import { LuCirclePlay } from "react-icons/lu";
1515
import { FaGithub } from "react-icons/fa";
1616
import { motion, AnimatePresence } from "framer-motion";
17-
import { ChevronLeft, ChevronRight } from "lucide-react";
1817

1918
export function Hero() {
2019
const [currentImage, setCurrentImage] = useState(0);
21-
const [isLoaded, setIsLoaded] = useState(false);
2220
const [isPaused, setIsPaused] = useState(false);
2321
const timerRef = useRef<NodeJS.Timeout | null>(null);
24-
const containerRef = useRef<HTMLDivElement>(null);
2522

2623
// 自动轮播功能
2724
useEffect(() => {
@@ -36,24 +33,6 @@ export function Hero() {
3633
};
3734
}, [isPaused]);
3835

39-
// 图片预加载
40-
useEffect(() => {
41-
if (typeof window !== 'undefined') {
42-
images.forEach((src) => {
43-
const imgEl = document.createElement('img');
44-
imgEl.src = src;
45-
});
46-
}
47-
}, []);
48-
49-
const goToNext = () => {
50-
setCurrentImage((prev) => (prev + 1) % images.length);
51-
};
52-
53-
const goToPrev = () => {
54-
setCurrentImage((prev) => (prev - 1 + images.length) % images.length);
55-
};
56-
5736
return (
5837
<div className="container relative z-[2] flex flex-col overflow-hidden rounded-lg bg-background px-6 pt-12 max-md:text-center md:px-12 md:pt-16">
5938
<div className="md:flex md:items-center md:gap-8 mb-8">
@@ -98,21 +77,19 @@ export function Hero() {
9877
</div>
9978

10079
<div
101-
ref={containerRef}
10280
className="relative mt-6 md:mt-8 mb-12 overflow-visible"
10381
onMouseEnter={() => setIsPaused(true)}
10482
onMouseLeave={() => setIsPaused(false)}
10583
>
106-
10784
<div className="relative w-full overflow-visible">
10885
<div className="w-full mx-auto overflow-hidden rounded-xl ring-1 ring-foreground/5 shadow-xl shadow-foreground/5">
10986
<div className="relative aspect-video w-full bg-gradient-to-br from-secondary/20 to-secondary/10">
11087
<AnimatePresence initial={false} mode="wait">
11188
<motion.div
11289
key={currentImage}
113-
initial={{ opacity: 0, y: 10 }}
114-
animate={{ opacity: 1, y: 0 }}
115-
exit={{ opacity: 0, y: -10 }}
90+
initial={{ opacity: 0, scale: 0.95 }}
91+
animate={{ opacity: 1, scale: 1 }}
92+
exit={{ opacity: 0, scale: 0.95 }}
11693
transition={{ duration: 0.5 }}
11794
className="absolute inset-0"
11895
>
@@ -124,62 +101,27 @@ export function Hero() {
124101
quality={90}
125102
priority={currentImage === 0}
126103
className="object-cover w-full"
127-
onLoadingComplete={() => setIsLoaded(true)}
128104
/>
129105
</motion.div>
130106
</AnimatePresence>
131-
132-
{/* 加载指示器 */}
133-
{!isLoaded && (
134-
<div className="absolute inset-0 flex items-center justify-center bg-gray-100 dark:bg-gray-800/90">
135-
<div className="w-12 h-12 border-4 border-gray-300 dark:border-gray-600 border-t-primary rounded-full animate-spin"></div>
136-
</div>
137-
)}
138-
139-
{/* 截图标题 */}
140-
<div className="absolute bottom-0 left-0 right-0 p-4 md:p-6 bg-gradient-to-t from-black/60 to-transparent">
141-
<div className="text-white font-medium text-lg md:text-xl">
142-
{imageNames[currentImage]}
143-
</div>
144-
</div>
145107
</div>
146108
</div>
147109

148-
{/* 左右箭头导航 */}
149-
<button
150-
onClick={goToPrev}
151-
className="absolute left-2 md:left-4 top-1/2 -translate-y-1/2 bg-background/80 dark:bg-background/60 backdrop-blur-sm p-2 rounded-full shadow-md hover:bg-background transition-colors border border-border"
152-
aria-label="上一张"
153-
>
154-
<ChevronLeft className="h-5 w-5" />
155-
</button>
156-
157-
<button
158-
onClick={goToNext}
159-
className="absolute right-2 md:right-4 top-1/2 -translate-y-1/2 bg-background/80 dark:bg-background/60 backdrop-blur-sm p-2 rounded-full shadow-md hover:bg-background transition-colors border border-border"
160-
aria-label="下一张"
161-
>
162-
<ChevronRight className="h-5 w-5" />
163-
</button>
164-
165-
{/* 进度条指示器 */}
166-
<div className="absolute bottom-[-20px] left-0 right-0 flex justify-center gap-2">
167-
<div className="flex gap-1.5">
168-
{images.map((_, index) => (
169-
<button
170-
key={`dot-${index}`}
171-
onClick={() => setCurrentImage(index)}
172-
className="group p-2"
173-
aria-label={`查看${imageNames[index]}`}
174-
>
175-
<div className={`h-1 w-6 rounded-full transition-all duration-500 ${
176-
index === currentImage
177-
? 'bg-primary w-10'
178-
: 'bg-muted-foreground/30 group-hover:bg-muted-foreground/50'
179-
}`} />
180-
</button>
181-
))}
182-
</div>
110+
<div className="absolute bottom-[calc(var(--spacing)*4)] left-1/2 -translate-x-1/2 z-[2] flex flex-row border border-[var(--color-fd-border)] rounded-full bg-[var(--color-fd-card)] p-1 shadow-md shadow-[var(--color-fd-background)]">
111+
{imageNames.map((name, index) => (
112+
<button
113+
key={`title-${index}`}
114+
onClick={() => setCurrentImage(index)}
115+
className={`px-4 py-2 rounded-full text-sm font-medium transition-all ${
116+
index === currentImage
117+
? 'bg-[var(--color-fd-accent)] text-[var(--color-fd-accent-foreground)]'
118+
: 'text-[var(--color-fd-muted-foreground)] hover:bg-[var(--color-fd-secondary)] hover:text-[var(--color-fd-secondary-foreground)]'
119+
}`}
120+
aria-label={`查看${name}`}
121+
>
122+
{name}
123+
</button>
124+
))}
183125
</div>
184126
</div>
185127
</div>

0 commit comments

Comments
 (0)