🎨 커스텀 JS 동적 배경 라이브러리 (최종 최적화 버전)
이 버전은 Canvas ID 불일치 해결 및 밝은 테마에서의 가시성 확보가 완료된 최종 버전입니다.
1. ✨ Twinkling Starfield (반짝이는 밤하늘)
배경을 어두운 남색으로 자동 설정하여 별이 잘 보이게 합니다.
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
let stars = [];
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
for(let i = 0; i < 150; i++) {
stars.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
size: Math.random() * 1.5,
opacity: Math.random(),
speed: Math.random() * 0.01 + 0.005
});
}
function animate() {
// 어두운 배경색 강제 지정 (별 가시성 확보)
ctx.fillStyle = '#0f172a';
ctx.fillRect(0, 0, canvas.width, canvas.height);
stars.forEach(s => {
s.opacity += s.speed;
if (s.opacity > 1 || s.opacity < 0) s.speed *= -1;
ctx.fillStyle = `rgba(255, 255, 255, ${Math.max(0, s.opacity)})`;
ctx.beginPath();
ctx.arc(s.x, s.y, s.size, 0, Math.PI * 2);
ctx.fill();
});
requestAnimationFrame(animate);
}
animate();
})();
2. 🌊 Smooth Wave Motion (부드러운 물결)
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
let tick = 0;
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
function drawWave(color, speed, height, offset) {
ctx.fillStyle = color;
ctx.beginPath();
ctx.moveTo(0, canvas.height);
for (let x = 0; x <= canvas.width; x++) {
const y = Math.sin(x * 0.01 + tick * speed + offset) * height + (canvas.height / 2);
ctx.lineTo(x, y);
}
ctx.lineTo(canvas.width, canvas.height);
ctx.fill();
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
tick++;
drawWave('rgba(59, 130, 246, 0.15)', 0.02, 20, 0);
drawWave('rgba(96, 165, 250, 0.1)', 0.015, 30, Math.PI);
requestAnimationFrame(animate);
}
animate();
})();
3. 🕸️ Particle Network (지적인 네트워크)
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const particles = [];
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
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.5,
vy: (Math.random() - 0.5) * 0.5
});
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
particles.forEach((p, i) => {
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.fillStyle = 'rgba(148, 163, 184, 0.4)';
ctx.beginPath(); ctx.arc(p.x, p.y, 2, 0, Math.PI*2); ctx.fill();
for(let j = i + 1; j < particles.length; j++) {
const p2 = particles[j];
const dist = Math.hypot(p.x - p2.x, p.y - p2.y);
if(dist < 100) {
ctx.strokeStyle = `rgba(148, 163, 184, ${1 - dist/100})`;
ctx.lineWidth = 0.5;
ctx.beginPath(); ctx.moveTo(p.x, p.y); ctx.lineTo(p2.x, p2.y); ctx.stroke();
}
}
});
requestAnimationFrame(animate);
}
animate();
})();
4. 🧬 Matrix Rain (디지털 비)
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const chars = "01".split("");
const fontSize = 14;
let columns;
let drops = [];
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
columns = Math.floor(canvas.width / fontSize);
drops = Array.from({length: columns}, () => Math.random() * -50);
}
window.addEventListener('resize', resize);
resize();
function animate() {
ctx.fillStyle = "rgba(0, 0, 0, 0.1)";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#0F0";
ctx.font = fontSize + "px monospace";
for (let i = 0; i < drops.length; i++) {
const text = chars[Math.floor(Math.random() * chars.length)];
ctx.fillText(text, i * fontSize, drops[i] * fontSize);
if (drops[i] * fontSize > canvas.height && Math.random() > 0.975) drops[i] = 0;
drops[i]++;
}
setTimeout(() => requestAnimationFrame(animate), 33);
}
animate();
})();
5. ❄️ Gentle Snowfall (겨울 눈)
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const snowflakes = [];
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
for(let i = 0; i < 100; i++) {
snowflakes.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
r: Math.random() * 3 + 1,
d: Math.random() * 1,
v: Math.random() * 0.8 + 0.4
});
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "rgba(255, 255, 255, 0.8)";
ctx.beginPath();
snowflakes.forEach(f => {
ctx.moveTo(f.x, f.y);
ctx.arc(f.x, f.y, f.r, 0, Math.PI * 2, true);
f.y += f.v;
f.x += Math.sin(f.d += 0.01);
if(f.y > canvas.height) {
f.y = -10;
f.x = Math.random() * canvas.width;
}
});
ctx.fill();
requestAnimationFrame(animate);
}
animate();
})();
6. 🏮 Floating Bubbles (비눗방울)
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const bubbles = [];
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
for(let i = 0; i < 30; i++) {
bubbles.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
r: Math.random() * 15 + 5,
s: Math.random() * 0.5 + 0.2
});
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
bubbles.forEach(b => {
b.y -= b.s;
if(b.y < -b.r) {
b.y = canvas.height + b.r;
b.x = Math.random() * canvas.width;
}
ctx.beginPath();
ctx.arc(b.x, b.y, b.r, 0, Math.PI * 2);
ctx.strokeStyle = "rgba(100, 100, 100, 0.2)";
ctx.stroke();
});
requestAnimationFrame(animate);
}
animate();
})();
7. 🌈 Gradient Flow (유동적 그라데이션)
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
let hue = Math.random() * 360;
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
function animate() {
hue = (hue + 0.1) % 360;
const grad = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
grad.addColorStop(0, `hsl(${hue}, 50%, 90%)`);
grad.addColorStop(1, `hsl(${(hue + 60) % 360}, 50%, 80%)`);
ctx.fillStyle = grad;
ctx.fillRect(0, 0, canvas.width, canvas.height);
requestAnimationFrame(animate);
}
animate();
})();
8. 📐 Geometric Float (떠다니는 도형)
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const shapes = [];
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
for(let i = 0; i < 15; i++) {
shapes.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
size: Math.random() * 40 + 20,
angle: Math.random() * Math.PI * 2,
rot: Math.random() * 0.02,
v: Math.random() * 0.5
});
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
shapes.forEach(s => {
s.angle += s.rot;
s.y -= s.v;
if(s.y < -s.size) {
s.y = canvas.height + s.size;
s.x = Math.random() * canvas.width;
}
ctx.save();
ctx.translate(s.x, s.y);
ctx.rotate(s.angle);
ctx.strokeStyle = "rgba(100, 100, 100, 0.1)";
ctx.strokeRect(-s.size/2, -s.size/2, s.size, s.size);
ctx.restore();
});
requestAnimationFrame(animate);
}
animate();
})();
9. ⚡ Aurora Borealis (오로라)
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
let time = 0;
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
time += 0.005;
for(let i = 0; i < 3; i++) {
const y = 30 + i * 15;
const grad = ctx.createLinearGradient(0, 0, 0, canvas.height);
grad.addColorStop(0, `rgba(52, 211, 153, ${0.3 - i*0.1})`);
grad.addColorStop(1, 'transparent');
ctx.fillStyle = grad;
ctx.beginPath();
ctx.moveTo(0, canvas.height);
for(let x = 0; x <= canvas.width; x += 10) {
const noise = Math.sin(x * 0.005 + time + i) * 50;
ctx.lineTo(x, y + noise);
}
ctx.lineTo(canvas.width, canvas.height);
ctx.fill();
}
requestAnimationFrame(animate);
}
animate();
})();
10. 🌑 Bokeh Background (컬러 보케 조명)
색상을 입혀 밝은 배경에서도 잘 보이게 수정되었습니다.
(function() {
const canvas = document.getElementById('bg-canvas');
if (!canvas) return;
const ctx = canvas.getContext('2d');
const circles = [];
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resize);
resize();
for(let i = 0; i < 25; i++) {
circles.push({
x: Math.random() * canvas.width,
y: Math.random() * canvas.height,
r: Math.random() * 100 + 50,
v: Math.random() * 0.2 + 0.1,
color: `hsla(${Math.random() * 360}, 70%, 70%, 0.3)`
});
}
function animate() {
// 배경을 살짝 어둡게 처리하여 보케 입자가 보이게 함
ctx.fillStyle = 'rgba(15, 23, 42, 0.05)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = "lighter";
circles.forEach(c => {
c.y -= c.v;
if(c.y < -c.r) {
c.y = canvas.height + c.r;
c.x = Math.random() * canvas.width;
}
const g = ctx.createRadialGradient(c.x, c.y, 0, c.x, c.y, c.r);
g.addColorStop(0, c.color);
g.addColorStop(1, "transparent");
ctx.fillStyle = g;
ctx.beginPath(); ctx.arc(c.x, c.y, c.r, 0, Math.PI*2); ctx.fill();
});
requestAnimationFrame(animate);
}
animate();
})();
댓글 0개
댓글을 작성하려면 로그인이 필요합니다.