feat(pages): 添加联系、首页和作品页面,更新样式和配置文件

This commit is contained in:
2026-06-26 10:36:54 +08:00
commit 44f0b43fcc
31 changed files with 5557 additions and 0 deletions

View File

@@ -0,0 +1,126 @@
import { useEffect, useRef } from 'react'
interface Particle {
x: number
y: number
size: number
speedX: number
speedY: number
opacity: number
}
export default function ParticleBackground() {
const canvasRef = useRef<HTMLCanvasElement>(null)
useEffect(() => {
const canvas = canvasRef.current
if (!canvas) return
const ctx = canvas.getContext('2d')
if (!ctx) return
let animationId: number
let particles: Particle[] = []
let mouseX = 0
let mouseY = 0
const resize = () => {
canvas.width = window.innerWidth
canvas.height = window.innerHeight
}
const createParticles = () => {
particles = []
const count = Math.floor((canvas.width * canvas.height) / 15000)
for (let i = 0; i < count; i++) {
particles.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
size: Math.random() * 2 + 0.5,
speedX: (Math.random() - 0.5) * 0.5,
speedY: (Math.random() - 0.5) * 0.5,
opacity: Math.random() * 0.5 + 0.1
})
}
}
const drawParticles = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height)
particles.forEach((particle, i) => {
particle.x += particle.speedX
particle.y += particle.speedY
if (particle.x < 0) particle.x = canvas.width
if (particle.x > canvas.width) particle.x = 0
if (particle.y < 0) particle.y = canvas.height
if (particle.y > canvas.height) particle.y = 0
ctx.beginPath()
ctx.arc(particle.x, particle.y, particle.size, 0, Math.PI * 2)
ctx.fillStyle = `rgba(102, 126, 234, ${particle.opacity})`
ctx.fill()
particles.forEach((particle2, j) => {
if (i === j) return
const dx = particle.x - particle2.x
const dy = particle.y - particle2.y
const distance = Math.sqrt(dx * dx + dy * dy)
if (distance < 150) {
ctx.beginPath()
ctx.strokeStyle = `rgba(102, 126, 234, ${0.15 * (1 - distance / 150)})`
ctx.lineWidth = 0.5
ctx.moveTo(particle.x, particle.y)
ctx.lineTo(particle2.x, particle2.y)
ctx.stroke()
}
})
const dx = particle.x - mouseX
const dy = particle.y - mouseY
const distance = Math.sqrt(dx * dx + dy * dy)
if (distance < 200) {
const force = (200 - distance) / 200
particle.speedX += (dx / distance) * force * 0.02
particle.speedY += (dy / distance) * force * 0.02
}
particle.speedX *= 0.99
particle.speedY *= 0.99
})
animationId = requestAnimationFrame(drawParticles)
}
const handleMouseMove = (e: MouseEvent) => {
mouseX = e.clientX
mouseY = e.clientY
}
resize()
createParticles()
drawParticles()
window.addEventListener('resize', () => {
resize()
createParticles()
})
window.addEventListener('mousemove', handleMouseMove)
return () => {
cancelAnimationFrame(animationId)
window.removeEventListener('resize', resize)
window.removeEventListener('mousemove', handleMouseMove)
}
}, [])
return (
<canvas
ref={canvasRef}
className="absolute inset-0 pointer-events-none"
style={{ zIndex: 1 }}
/>
)
}