|
|
@ -62,10 +62,12 @@ function HeroParticleCanvas() { |
|
|
y: Math.random() * H, |
|
|
y: Math.random() * H, |
|
|
vx: (Math.random() - 0.5) * 0.10, // 速度砍 71%,停止"游来游去"的感觉
|
|
|
vx: (Math.random() - 0.5) * 0.10, // 速度砍 71%,停止"游来游去"的感觉
|
|
|
vy: (Math.random() - 0.5) * 0.10, |
|
|
vy: (Math.random() - 0.5) * 0.10, |
|
|
r: Math.random() * 1.4 + 0.6, |
|
|
// 浅底可见版:粒子尺寸 +33%(原 0.6~2.0 → 现 0.8~2.6)
|
|
|
|
|
|
r: Math.random() * 1.8 + 0.8, |
|
|
color: PALETTE[Math.floor(Math.random() * PALETTE.length)], |
|
|
color: PALETTE[Math.floor(Math.random() * PALETTE.length)], |
|
|
alpha: Math.random() * 0.5 + 0.4, |
|
|
// 浅底可见版:alpha 基准 +30%(原 0.4~0.9 → 现 0.65~0.95)
|
|
|
alphaSpeed: (Math.random() - 0.5) * 0.008, |
|
|
alpha: Math.random() * 0.30 + 0.65, |
|
|
|
|
|
alphaSpeed: (Math.random() - 0.5) * 0.009, |
|
|
})); |
|
|
})); |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
@ -96,24 +98,25 @@ function HeroParticleCanvas() { |
|
|
if (p.y < p.r) { p.y = p.r; p.vy = Math.abs(p.vy); } |
|
|
if (p.y < p.r) { p.y = p.r; p.vy = Math.abs(p.vy); } |
|
|
if (p.y > H - p.r) { p.y = H - p.r; p.vy = -Math.abs(p.vy); } |
|
|
if (p.y > H - p.r) { p.y = H - p.r; p.vy = -Math.abs(p.vy); } |
|
|
|
|
|
|
|
|
// 闪烁 alpha
|
|
|
// 闪烁 alpha(浅底版:最低不低于 0.55 保证可见)
|
|
|
p.alpha += p.alphaSpeed; |
|
|
p.alpha += p.alphaSpeed; |
|
|
if (p.alpha > 0.95 || p.alpha < 0.35) p.alphaSpeed = -p.alphaSpeed; |
|
|
if (p.alpha > 0.98 || p.alpha < 0.55) p.alphaSpeed = -p.alphaSpeed; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
ctx.beginPath(); |
|
|
ctx.beginPath(); |
|
|
const g = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.r * 3); |
|
|
// 浅底可见版:发光半径 r×3.5(原 r×3),中间色 alpha*0.45(原 *0.35)
|
|
|
|
|
|
const g = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.r * 3.5); |
|
|
g.addColorStop(0, `rgba(${p.color}, ${p.alpha})`); |
|
|
g.addColorStop(0, `rgba(${p.color}, ${p.alpha})`); |
|
|
g.addColorStop(0.5, `rgba(${p.color}, ${p.alpha * 0.35})`); |
|
|
g.addColorStop(0.5, `rgba(${p.color}, ${p.alpha * 0.45})`); |
|
|
g.addColorStop(1, `rgba(${p.color}, 0)`); |
|
|
g.addColorStop(1, `rgba(${p.color}, 0)`); |
|
|
ctx.fillStyle = g; |
|
|
ctx.fillStyle = g; |
|
|
ctx.arc(p.x, p.y, p.r * 3, 0, Math.PI * 2); |
|
|
ctx.arc(p.x, p.y, p.r * 3.5, 0, Math.PI * 2); |
|
|
ctx.fill(); |
|
|
ctx.fill(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// 2) 邻近连线(仅动画模式执行,静态省开销)
|
|
|
// 2) 邻近连线(浅底可见版:MAX+25%,基础 alpha+50%,线宽 x1.43)
|
|
|
if (!reduced) { |
|
|
if (!reduced) { |
|
|
const MAX = 120; |
|
|
const MAX = 150; // 原 120 → +25%
|
|
|
for (let i = 0; i < particles.length; i++) { |
|
|
for (let i = 0; i < particles.length; i++) { |
|
|
const a = particles[i]; |
|
|
const a = particles[i]; |
|
|
for (let j = i + 1; j < particles.length; j++) { |
|
|
for (let j = i + 1; j < particles.length; j++) { |
|
|
@ -129,11 +132,11 @@ function HeroParticleCanvas() { |
|
|
const adx = a.x - mouse.x, ady = a.y - mouse.y; |
|
|
const adx = a.x - mouse.x, ady = a.y - mouse.y; |
|
|
const bdx = b.x - mouse.x, bdy = b.y - mouse.y; |
|
|
const bdx = b.x - mouse.x, bdy = b.y - mouse.y; |
|
|
const near = Math.min(adx * adx + ady * ady, bdx * bdx + bdy * bdy); |
|
|
const near = Math.min(adx * adx + ady * ady, bdx * bdx + bdy * bdy); |
|
|
if (near < 120 * 120) boost = (1 - Math.sqrt(near) / 120) * 0.45; |
|
|
if (near < 140 * 140) boost = (1 - Math.sqrt(near) / 140) * 0.65; // 原 0.45 → +44%
|
|
|
} |
|
|
} |
|
|
const alpha = Math.min(0.55, t * 0.28 + boost); |
|
|
const alpha = Math.min(0.72, t * 0.42 + boost); // 原 0.55 / t*0.28 → 大幅增强
|
|
|
ctx.strokeStyle = `rgba(148, 184, 255, ${alpha})`; |
|
|
ctx.strokeStyle = `rgba(100, 140, 230, ${alpha})`; // 颜色略深,浅底上对比更强
|
|
|
ctx.lineWidth = 0.7; |
|
|
ctx.lineWidth = 1.0; // 原 0.7 → x1.43
|
|
|
ctx.beginPath(); |
|
|
ctx.beginPath(); |
|
|
ctx.moveTo(a.x, a.y); |
|
|
ctx.moveTo(a.x, a.y); |
|
|
ctx.lineTo(b.x, b.y); |
|
|
ctx.lineTo(b.x, b.y); |
|
|
@ -215,15 +218,15 @@ export default function Home({ locale }: { locale: Locale }) { |
|
|
|
|
|
|
|
|
return ( |
|
|
return ( |
|
|
<> |
|
|
<> |
|
|
{/* ===== HERO:品牌背景图 + Canvas 粒子网 + 雾化光晕 + 玻璃球轨道粒子 ===== */} |
|
|
{/* ===== HERO:极简版(用户反馈满屏星星太脏)—— 只保留干净 hero-bg.jpg 原图 + 左下文字阴影 ===== */} |
|
|
<section |
|
|
<section |
|
|
className="relative w-full h-[calc(100vh-60px)] min-h-[520px] max-h-[900px] overflow-hidden" |
|
|
className="hero-text-visible relative w-full h-[calc(100vh-60px)] min-h-[520px] max-h-[900px] overflow-hidden" |
|
|
style={{ |
|
|
style={{ |
|
|
background: |
|
|
background: |
|
|
'linear-gradient(135deg, #0a0e2a 0%, #14182f 50%, #1d2150 100%)', |
|
|
'linear-gradient(135deg, #f2f5ff 0%, #e8eeff 50%, #eeeaff 100%)', /* 极淡蓝紫,与 hero-bg.jpg 边缘无缝衔接 */ |
|
|
}} |
|
|
}} |
|
|
> |
|
|
> |
|
|
{/* 背景图:玻璃球/水滴主题图,匹配品牌色 */} |
|
|
{/* 背景图:玻璃球/水滴主题图,原图直接展示,不叠加任何蒙层/粒子/光晕/星芒 */} |
|
|
<img |
|
|
<img |
|
|
src="/hero-bg.jpg" |
|
|
src="/hero-bg.jpg" |
|
|
alt="" |
|
|
alt="" |
|
|
@ -234,71 +237,6 @@ export default function Home({ locale }: { locale: Locale }) { |
|
|
decoding="async" |
|
|
decoding="async" |
|
|
/> |
|
|
/> |
|
|
|
|
|
|
|
|
{/* 方案A:半透明深色蒙层 → 让粒子/光晕从浅色背景中"显形",同时增强左下白字对比度 */} |
|
|
|
|
|
<div |
|
|
|
|
|
aria-hidden="true" |
|
|
|
|
|
className="absolute inset-0 pointer-events-none" |
|
|
|
|
|
style={{ |
|
|
|
|
|
zIndex: 1, |
|
|
|
|
|
background: |
|
|
|
|
|
'linear-gradient(135deg, rgba(10, 14, 42, 0.62) 0%, rgba(20, 24, 47, 0.54) 50%, rgba(29, 33, 80, 0.50) 100%)', |
|
|
|
|
|
}} |
|
|
|
|
|
/> |
|
|
|
|
|
|
|
|
|
|
|
{/* 雾化光晕 4 球(慢速漂浮,最底层之上但粒子网之下) */} |
|
|
|
|
|
<div aria-hidden="true" className="absolute inset-0 pointer-events-none" style={{ zIndex: 2, overflow: 'hidden' }}> |
|
|
|
|
|
{HERO_GLOW_ORBS.map((o, i) => ( |
|
|
|
|
|
<span |
|
|
|
|
|
key={i} |
|
|
|
|
|
className="hero-glow-orb" |
|
|
|
|
|
style={cssVars({ |
|
|
|
|
|
'--orb-x': o.x, |
|
|
|
|
|
'--orb-y': o.y, |
|
|
|
|
|
'--orb-sz': o.sz + 'px', |
|
|
|
|
|
'--orb-color': o.c, |
|
|
|
|
|
animationName: o.anim, |
|
|
|
|
|
animationDelay: o.delay, |
|
|
|
|
|
})} |
|
|
|
|
|
/> |
|
|
|
|
|
))} |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
{/* Canvas 全屏粒子 + 邻近连线(白/蓝/紫/粉 4 色),z-index:3 */} |
|
|
|
|
|
<HeroParticleCanvas /> |
|
|
|
|
|
|
|
|
|
|
|
{/* 粒子层:环绕中央玻璃球的轨道粒子(7 圈 / 22 颗,4 色分色,linear 匀速环绕) */} |
|
|
|
|
|
<div className="hero-orbit pointer-events-none" aria-hidden="true" style={{ left: '70%', top: '46%', zIndex: 4 }}> |
|
|
|
|
|
{orbits.flatMap((o, i) => |
|
|
|
|
|
o.dots.map((d, j) => { |
|
|
|
|
|
// 全局 dot 序号,用于 stagger 脉冲相位 + 颜色循环
|
|
|
|
|
|
const globalIdx = orbits.slice(0, i).reduce((n, x) => n + x.dots.length, 0) + j; |
|
|
|
|
|
const palette = DOT_PALETTE[globalIdx % DOT_PALETTE.length]; |
|
|
|
|
|
return ( |
|
|
|
|
|
<div |
|
|
|
|
|
key={`${i}-${j}`} |
|
|
|
|
|
className={`hero-ring${o.rev ? ' is-rev' : ''}`} |
|
|
|
|
|
style={{ |
|
|
|
|
|
animationDuration: o.d, |
|
|
|
|
|
animationDirection: o.rev ? 'reverse' : 'normal', |
|
|
|
|
|
'--r': `${o.r}px`, |
|
|
|
|
|
} as CSSProperties} |
|
|
|
|
|
> |
|
|
|
|
|
<div className="hero-orbit-slot" style={{ '--a': d.a } as CSSProperties}> |
|
|
|
|
|
<span |
|
|
|
|
|
className={`hero-orbit-dot dot-${palette}`} |
|
|
|
|
|
style={{ |
|
|
|
|
|
width: d.sz, |
|
|
|
|
|
height: d.sz, |
|
|
|
|
|
animationDelay: `${-(globalIdx * 0.35).toFixed(2)}s`, |
|
|
|
|
|
}} |
|
|
|
|
|
/> |
|
|
|
|
|
</div> |
|
|
|
|
|
</div> |
|
|
|
|
|
); |
|
|
|
|
|
}), |
|
|
|
|
|
)} |
|
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
|
|
<div className="relative z-10 h-full w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex flex-col justify-end pb-16 md:pb-24"> |
|
|
<div className="relative z-10 h-full w-full max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 flex flex-col justify-end pb-16 md:pb-24"> |
|
|
<div className="max-w-3xl scroll-reveal"> |
|
|
<div className="max-w-3xl scroll-reveal"> |
|
|
<h1 className="text-h1 font-bold leading-[1.1] tracking-tight text-white font-[var(--font-display)]"> |
|
|
<h1 className="text-h1 font-bold leading-[1.1] tracking-tight text-white font-[var(--font-display)]"> |
|
|
|