이번 글에서는 HTML, CSS, JavaScript만을 사용해서
배경에 자연스럽게 움직이는 파티클(입자) 애니메이션 효과를 구현하는 과정을 정리한다.
웹사이트의 시각적인 매력을 더해주는 배경 입자 효과는 종종 포트폴리오, 랜딩 페이지, 인터랙션 UI 등에서 사용된다.
이 효과는 단순한 시각 장식 이상으로 사용자에게 생동감 있는 경험을 제공한다.
**Particle(입자)**은 말 그대로 작고 개별적인 요소를 말한다.
웹에서의 파티클 효과는 수많은 작은 도형들이 자유롭게 움직이거나 상호작용하는 애니메이션 배경을 의미한다.
이 효과는 기본 HTML/CSS만으로는 구현할 수 없고,
<canvas> 태그와 JavaScript의 그래픽 API를 활용해야 한다.
<canvas> 요소로 그래픽 영역 생성)<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Particle Background</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body, html {
width: 100%;
height: 100%;
overflow: hidden;
}
canvas {
position: fixed;
top: 0;
left: 0;
display: block;
z-index: -1;
}
</style>
</head>
<body>
<canvas id="particleCanvas"></canvas>
<script src="particle.js"></script>
</body>
</html>
<canvas>는 도형을 그릴 수 있는 HTML 요소position: fixed와 z-index: -1 설정으로 배경처럼 뒤에 깔림let canvas, ctx, particles = []
canvas: HTML의 캔버스 DOM 요소ctx: 2D 그래픽을 그릴 수 있는 컨텍스트particles: 모든 입자 정보를 담는 배열function initParticles() {
canvas = document.getElementById('particleCanvas')
ctx = canvas.getContext('2d')
resizeCanvas()
createParticles()
animateParticles()
window.addEventListener('resize', resizeCanvas)
}
ctx로 그림을 그릴 준비를 한다resizeCanvas()로 화면 크기에 맞춤createParticles()로 랜덤 입자 50개 생성animateParticles()로 프레임마다 입자 애니메이션 실행function resizeCanvas() {
canvas.width = window.innerWidth
canvas.height = window.innerHeight
}
function createParticles() {
particles = []
for (let i = 0; i < 50; i++) {
particles.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
vx: (Math.random() - 0.5) * 0.3,
vy: (Math.random() - 0.5) * 0.3,
size: Math.random() * 2 + 1,
opacity: Math.random() * 0.3 + 0.1,
})
}
}
function animateParticles() {
ctx.clearRect(0, 0, canvas.width, canvas.height)
particles.forEach((p) => {
p.x += p.vx
p.y += p.vy
if (p.x < 0 || p.x > canvas.width) p.vx *= -1
if (p.y < 0 || p.y > canvas.height) p.vy *= -1
ctx.save()
ctx.globalAlpha = p.opacity
ctx.fillStyle = '#dc2626'
ctx.beginPath()
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2)
ctx.fill()
ctx.restore()
})
drawConnections()
requestAnimationFrame(animateParticles)
}
ctx.arc()로 동그라미 그리기requestAnimationFrame()으로 부드러운 반복 렌더링 처리function drawConnections() {
for (let i = 0; i < particles.length; i++) {
for (let j = i + 1; j < particles.length; j++) {
const dx = particles[i].x - particles[j].x
const dy = particles[i].y - particles[j].y
const distance = Math.sqrt(dx * dx + dy * dy)
if (distance < 100) {
ctx.beginPath()
ctx.strokeStyle = 'rgba(220, 38, 38, 0.1)'
ctx.moveTo(particles[i].x, particles[i].y)
ctx.lineTo(particles[j].x, particles[j].y)
ctx.stroke()
}
}
}
}
initParticles()
이번 프로젝트는 canvas와 JavaScript만으로도 매우 아름답고 가벼운 배경 애니메이션을 구현할 수 있다는 것을 보여준다.
canvas와 2D context 사용법requestAnimationFrame()의 중요성