이전 글 : [Canvas-불꽃놀이-06] TextData 클래스
Particle들의 부모 클래스 생성
1. 부모 Particle 클래스를 생성하려는 이유
- 불꽃놀이에 필요한 파티클의 종류를 4가지로 결정했다.
- TailParticle : 불꽃놀이의 꼬리 부분을 표현하는 파티클
- SparkParticle : 불꽃놀이 잔상 효과를 표현하는 파티클
- TextParticle : 사용자가 입력한 텍스트를 표현하는 파티클
- CircleParticle : TextParticle과 같이 터지는 원형의 불꽃 파티클
- 위의 파티클들은 유사한 효과를 내기에 공통 속성과 기능을 가진 부모인 Particle 클래스를 만들어 중복을 피하고 유지보수에 용이하게 했다.
- Particle 클래스에서는 위치, 속도, 색상, 투명도 등의 멤버변수와 애니메이션 업데이트 등 공통된 메서드를 정의해 각 파티클의 고유한 효과만 구현하도록 해주어 효율적이고 확정성 높은 구조를 가지게 된다.
2. 공통 로직를 관리하는 utils.js 파일 생성
- 파티클 클래스 생성을 진행하다가 범용적으로 쓰일 로직이 있어 utils.js 파일을 생성해 관리하기로 하였다.
- random 값을 리턴하는 랜덤 함수
// min과 max 사이의 소수점 decimal(기본값:2)자리의 랜덤한 소수 반환
export function randomFloat(min, max, decimal = 2) {
return parseFloat((Math.random() * (max - min) + min).toFixed(decimal));
}
// min과 max 사이의 랜덤한 정수 반환
export function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
- rgba, hsla 두 가지 종류로 파티클의 색상을 정의할 수 있으며 컬러값과 투명도를 통해 다양한 컬러를 표현할 수 있도록 구현했다.
- rgba로도 많은 색상을 표현할 수 있으나 좀 더 다양한 컬러감을 보여주기 위해 빛, 채도 조절이 가능한 hsla 색상 모델을 추가하였다.
// 파티클 색성에 적용할 RGBA 문자열 반환
export function setRgbaColor(rgb = PARTICLE.RGB, opacity = 1) {
return `rgba(${rgb}, ${opacity})`;
}
// 파티클 색상애 적용할 HSLA 문자열 반환
export function setHslaColor(params = {}) {
const {
hue = PARTICLE.HUE,
saturation = randomInt(PARTICLE.MIN_SATURATION, PARTICLE.MAX_SATURATION),
lightness = randomInt(PARTICLE.MIN_LIGHTNESS, PARTICLE.MAX_LIGHTNESS),
} = params;
return `hsla(${hue}, ${saturation}%, ${lightness}%)`;
}
3. Particle과 관련된 상수값 추가
- 각 파일들의 상수를 관리하는 constants.js에 Particle과 관련된 상수값을 추가했다.
export const PARTICLE = {
RGB: "255, 255, 210",
HUE: 20,
MIN_SATURATION: 50,
MAX_SATURATION: 100,
MIN_LIGHTNESS: 50,
MAX_LIGHTNESS: 100,
MIN_OPACITY: 0.9,
MAX_OPACITY: 1,
RADIUS: 1,
RADIUS_ADJUST_RATIO: 0.8,
FRICTION: 0.93,
};
4. Particle 클래스 생성
- Particle 클래스는 파티클들의 공통 속성을 정의하며 애니메이션을 위해 필요한 ctx, isSmallScreen을 생성 시 넘겨받아 불필요한 의존성을 줄였다.
- 생성자에서는 모든 파티클들의 공통 속성을 파라미터로 넘겨받고 추후 객체폴링 적용을 위해 ctx, isSmallScreen 외 다른 멤버변수를 초기화하는 함수를 구현했다.
- 멤버변수의 개수가 많기 때문에 객체를 통해 넘겨받았다.
- 좀 더 자연스러운 시각효과를 위해 화면 크기에 따라 radius 값을 조절할 수 있게 하였다.
// Particle.js
class Particle {
// ctx, isSmallScreen은 CanvasOption 클래스에서 정의해서 전달 받은 값
// 나머지 변수는 파티클 클래스의 멤버 변수
constructor({ ctx, isSmallScreen, x, y, vx, vy, radius, opacity, friction, color }) {
this.ctx = ctx;
this.isSmallScreen = isSmallScreen;
// 파티클 멤버 변수 초기화
this.initParticleVars({ x, y, vx, vy, radius, opacity, friction, color });
}
// 기본값을 적용하여 변경이 필요한 변수만 생성시 넘겨 받은 값으로 정의
initParticleVars(params = {}) {
const {
x = 0,
y = 0,
vx = 0,
vy = 0,
radius = PARTICLE.RADIUS,
opacity = randomFloat(PARTICLE.MIN_OPACITY, PARTICLE.MAX_OPACITY),
friction = PARTICLE.FRICTION,
color = setRgbaColor(PARTICLE.RGB, opacity),
} = params;
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.radius = this.isSmallScreen ? radius * PARTICLE.RADIUS_ADJUST_RATIO : radius;
this.opacity = opacity;
this.friction = friction;
this.fillColor = color;
}
}
5. 애니메이션 메서드
- 애니메이션 적용을 위한 공통 메서드를 생성하였다.
- 캔버스 화면에 그리는 draw 함수를 구현하였다. 일단 파티클은 원의 형태로 그릴 거 기 때문에 arc 메서드를 사용하였다.
// Particle.js
draw() {
// 캔버스에 그림을 그리기 위한 새로운 경로를 생성한다.
this.ctx.beginPath();
// 파티클을 채울 색상 설정
this.ctx.fillStyle = this.fillColor;
// 캔버스에 x, y위치에 반지름이 radius인 원을 생성한다.
this.ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2);
// 설정된 색상으로 원을 채운다
this.ctx.fill();
// 현재 경로를 닫아 그리기를 종료한다.
this.ctx.closePath();
}
- 캔버스의 상태변화를 업데이트할 메서드를 생성하였다.
- 속도, 좌표 업데이트 메서드를 따로 만들어 유연하게 적용할 수 있게 했고 그 둘을 합친 기본 업데이트 메서드를 구현했다.
// x, y의 속도을 업데이트한다.
// 속도에 마찰 계수를 곱해 파티클이 퍼져나가면서 점차 멈추는 자연스런 효과를 낼 수 있다.
updateVelocity() {
this.vx *= this.friction;
this.vy *= this.friction;
}
// 업데이트된 속도에 맞춰 x, y의 위치를 업데이트한다.
updatePosition() {
this.x += this.vx;
this.y += this.vy;
}
// 속도와 좌표 업데이트 합친 기본적인 업데이트 메서드를 구현했다.
update() {
this.updateVelocity();
this.updatePosition();
}
Github 링크
'Canvas > 불꽃놀이 프로젝트' 카테고리의 다른 글
[Canvas-불꽃놀이-09] 파티클 관리와 객체 폴링 (1) | 2024.11.22 |
---|---|
[Canvas-불꽃놀이-08] 애니메이션 기본 틀잡기 (0) | 2024.11.20 |
[Canvas-불꽃놀이-06] TextData 클래스 (2) | 2024.11.18 |
[Canvas-불꽃놀이-05] index.js에서 중요 이벤트 정의 (1) | 2024.11.18 |
[Canvas-불꽃놀이-04] Canvas 설정 - 물리적 크기와 CSS 크기 (0) | 2024.11.17 |