[Canvas-불꽃놀이-07] 불꽃놀이 Particle들의 부모 클래스

이전 글 : [Canvas-불꽃놀이-06] TextData 클래스

 

[Canvas-불꽃놀이-06] TextData 클래스

이전 글 : 2024.11.18 - [개발/Canvas] - [Canvas-불꽃놀이-05] 화면 전환, 입력 이벤트 정의 [Canvas-불꽃놀이-05] 화면 전환, 입력 이벤트 정의이전글 : 2024.11.17 - [개발/Canvas] - [Canvas-불꽃놀이-04] Canvas 설정

jinsk-joy.tistory.com

 

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 링크

 

GitHub - jinsk9268/text-fireworks

Contribute to jinsk9268/text-fireworks development by creating an account on GitHub.

github.com