94 lines
2.9 KiB
React
94 lines
2.9 KiB
React
import React, { useState, useEffect, useCallback } from 'react'
|
|
import CertificateCard, { certificates } from './CertificateCard'
|
|
|
|
export default function CertificateCarousel() {
|
|
const [active, setActive] = useState(2) // 从中间开始 (ISO 45001)
|
|
const [isMobile, setIsMobile] = useState(false)
|
|
|
|
// 检测是否为移动端
|
|
useEffect(() => {
|
|
const check = () => setIsMobile(window.innerWidth < 768)
|
|
check()
|
|
window.addEventListener('resize', check)
|
|
return () => window.removeEventListener('resize', check)
|
|
}, [])
|
|
|
|
const next = useCallback(() => {
|
|
setActive(prev => (prev + 1) % certificates.length)
|
|
}, [])
|
|
|
|
// 自动轮播
|
|
useEffect(() => {
|
|
const timer = setInterval(next, 3000)
|
|
return () => clearInterval(timer)
|
|
}, [next])
|
|
|
|
const goTo = (index) => setActive(index)
|
|
|
|
// 响应式参数
|
|
const containerHeight = isMobile ? 'h-[360px]' : 'h-[600px]'
|
|
const translateXBase = isMobile ? 140 : 260
|
|
const scaleCenter = 1.0
|
|
const scaleNear = isMobile ? 0.8 : 0.7
|
|
const scaleFar = isMobile ? 0.5 : 0.4
|
|
|
|
return (
|
|
<div className="relative max-w-4xl mx-auto">
|
|
{/* 证书展示区 */}
|
|
<div className={`relative ${containerHeight} flex items-center justify-center`}>
|
|
{certificates.map((cert, i) => {
|
|
let offset = i - active
|
|
|
|
// 循环环绕:取最短路径
|
|
if (offset > 2) offset = offset - certificates.length
|
|
if (offset < -2) offset = offset + certificates.length
|
|
|
|
const absOffset = Math.abs(offset)
|
|
|
|
let scale = scaleCenter
|
|
if (absOffset === 1) scale = scaleNear
|
|
if (absOffset >= 2) scale = scaleFar
|
|
|
|
let opacity = 1
|
|
if (absOffset === 1) opacity = 0.6
|
|
if (absOffset >= 2) opacity = 0
|
|
|
|
let translateX = offset * translateXBase
|
|
|
|
let zIndex = 10 - absOffset
|
|
|
|
return (
|
|
<div
|
|
key={cert.id}
|
|
className="absolute transition-all duration-500 ease-in-out cursor-pointer"
|
|
style={{
|
|
transform: `translateX(${translateX}px) scale(${scale})`,
|
|
opacity,
|
|
zIndex,
|
|
filter: absOffset >= 2 ? 'blur(2px)' : 'none',
|
|
}}
|
|
onClick={() => goTo(i)}
|
|
>
|
|
<CertificateCard certificate={cert} index={i} scale={isMobile ? 0.7 : 1} />
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
|
|
{/* 底部指示点 */}
|
|
<div className="flex justify-center gap-2 mt-4">
|
|
{certificates.map((cert, i) => (
|
|
<button
|
|
key={cert.id}
|
|
onClick={() => goTo(i)}
|
|
className={`w-2 h-2 rounded-full transition-all duration-300 ${
|
|
i === active
|
|
? 'bg-[#004ec4] w-6'
|
|
: 'bg-[#004ec4]/30 hover:bg-[#004ec4]/50'
|
|
}`}
|
|
/>
|
|
))}
|
|
</div>
|
|
</div>
|
|
)
|
|
} |