원래 오늘 js중 processing 과 같은 라이브러리가 있어 그것을 하려고 했지만 시간이 없어서 이번에도 canvsJS로 한다 (다음: p5.js)
html 전체 코드
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body{
padding: 0;
margin: 0;
height: 100vh;
background-color: black;
}
#canvas{
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
canvasJS코드
let canvas, ctx, w, h, particles = [];
let mouse = {
x: undefined,
y: undefined
}
const init = ()=> {
canvas = document.querySelector("#canvas");
ctx = canvas.getContext("2d");
resizeReset();
animationLoop();
}
const resizeReset = () => {
w = canvas.width = window.innerWidth;
h = canvas.height = window.innerHeight;
}
const mouseMove = (e) => {
mouse.x = e.x;
mouse.y = e.y;
}
const mouseOut = () => {
mouse.x = undefined;
mouse.y = undefined;
}
const animationLoop = () => {
if (mouse.x != undefined && mouse.y != undefined) {
particles.push(new Particle(mouse.x, mouse.y));
}
ctx.clearRect(0, 0, w, h);
ctx.globalCompositeOperation = 'lighter';
drawScene();
arrayCleanup();
requestAnimationFrame(animationLoop);
}
const arrayCleanup = () => {
let dump = [];
particles.map((particle) => {
if (particle.radius > 0) {
dump.push(particle);
}
});
particles = dump;
}
const drawScene = () => {
particles.map((particle) => {
particle.update();
particle.draw();
})
}
class Particle {
constructor(x, y) {
this.x = x;
this.y = y;
this.radius = 5;
this.size = 0;
this.rotate = 0;
this.alpha = 0.5;
}
setPoint() {
let r, x, y;
this.point = [];
for (let a = 0; a < 360; a += 10) {
r = (Math.PI / 180) * (a + this.rotate);
x = this.x + this.size * Math.sin(r);
y = this.y + this.size * Math.cos(r);
this.point.push({ x: x, y: y, r: this.radius });
}
}
draw() {
if (this.radius <= 0) return;
this.point.map((p) => {
ctx.beginPath();
ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
ctx.fillStyle = `hsla(160, 100%, 50%, ${this.alpha})`;
ctx.fill();
ctx.closePath();
});
}
update() {
this.setPoint();
this.radius -= 0.05;
this.size += 0.5;
this.rotate -= 1;
this.alpha = (this.radius * 0.5 < 0.5) ? this.radius * 0.5 : 0.5;
}
}
window.addEventListener("DOMContentLoaded", init);
window.addEventListener("resize", resizeReset);
window.addEventListener("mousemove", mouseMove);
window.addEventListener("mouseout", mouseOut);
다음은 함수별 설명
init(): 이 함수는 캔버스를 초기화하고 2D 렌더링 컨텍스트 (ctx)를 가져온 다음, resizeReset() 함수를 호출하여 캔버스 크기를 창의 내부 크기와 일치하도록 설정하고, animationLoop()를 호출하여 애니메이션 루프를 시작함니다.
resizeReset(): 이 함수는 캔버스 크기를 창의 내부 크기와 일치하도록 설정하는 역할을 담당합니다. 캔버스의 너비 (w)와 높이 (h)를 창의 내부 너비와 높이로 설정합니다.
mouseMove(e): 이 함수는 마우스 이동 이벤트를 처리하여 마우스 위치를 따라 갑니다. e 매개변수는 이벤트 객체를 나타내고, 이벤트가 발생할 때마다 mouse.x와 mouse.y 속성을 현재 마우스 좌표로 업데이트합니다.
mouseOut(): 이 함수는 mouseMove()와 반대로 마우스가 켄버스 영역을 벗어나면 mouse.x와 mouse.y 를 undefined 마우스 위치를 재조정 시킨다.
animationLoop(): 애니메이션을 위한 루프 함수입니다. 마우스 좌표가 정의되어 있다면 새로운 파티클을 생성합니다. 그런 다음 캔버스를 지우고, drawScene 함수를 호출하여 모든 파티클을 업데이트하고 그려줍니다. 마지막으로 requestAnimationFrame을 사용하여 다음 프레임을 요청합니다.
arrayCleanup(): 파티클 배열을 정리하는 함수입니다. 반지름이 0보다 큰 파티클만을 유지하고, 나머지는 삭제합니다.
drawScene(): 파티클 배열을 순회하면서 각 파티클을 업데이트하고 그립니다.
Particle{} : 파티클을 나타내는 클래스입니다. 생성자에서는 파티클의 초기 위치와 속성을 정의합니다.
setPoint(): 함수에서는 파티클 주위의 점들을 계산하여 point 배열에 저장합니다.
draw(): 함수에서는 point 배열을 순회하면서 각 점을 캔버스에 그리고, update(): 함수에서는 파티클의 속성을 업데이트합니다.
점점 귀찮아 지기는 하지만 다음 부터는 vlog에서 보다 tistory 에서 올려 볼려고 한다 이름은 다음 시간에올려 보겠다.