파티클 만들기

*particle: 입자

겨울밤 이미지의 배경을 캔버스에 그리기

01.JPG

const ctxW = ctx.canvas.width;
const ctxH = ctx.canvas.height;

const bgImage = new Image();
bgImage.src = '/winternight.jpg';

function animate() {
  ctx.clearRect(0, 0, ctxW, ctxH);
  ctx.drawImage(bgImage, 0, 0);
  requestAnimationFrame(animate);
}

requestAnimationFrame(animate);

화면에 눈송이 하나 그리기

02.gif

let y = 0;

// 눈송이를 그린다.
function snow() {
  ctx.fillStyle = 'rgba(255, 255, 255, 0.75)';
  ctx.beginPath();
  ctx.arc(100, y++, 5, 0, Math.PI * 2);
  ctx.fill();
}

// 매 시간 화면을 갱신한다.
function animate() {
  ctx.clearRect(0, 0, ctxW, ctxH);
  ctx.drawImage(bgImage, 0, 0);
  snow();
  requestAnimationFrame(animate);
}

requestAnimationFrame(animate);

눈송이가 내릴 위치인 x 좌표와 눈송이의 크기를 랜덤하게 바꾸기

03.gif

// x 좌표를 랜덤으로 변경한다.
let x = Math.floor(Math.random() * ctxW) + 1;
let y = 0;
// 눈송이의 크기를 랜덤으로 변경한다.
const size = Math.floor(Math.random() * 3) + 1;

// 눈송이를 그린다.
function snow() {
  ctx.fillStyle = 'rgba(255, 255, 255, 0.75)';
  ctx.beginPath();
  ctx.arc(x, y++, size, 0, Math.PI * 2);
  ctx.fill();
}

눈송이를 여러 개 만들어 화면에 내리게 만들기

04.gif

const snowflakes = [];
const totalCount = 10;

/// 눈송이를 추가한다.
function addSnowflake() {
  if (snowflakes.length >= totalCount) return;

  // x 좌표를 랜덤으로 변경한다.
  let x = Math.floor(Math.random() * ctxW) + 1;
  let y = 0;
  // 눈송이의 크기를 랜덤으로 변경한다.
  const size = Math.floor(Math.random() * 3) + 1;

  snowflakes.push({ x, y, size });
}

// 눈송이를 그린다.
function snow() {
  addSnowflake();

  ctx.fillStyle = 'rgba(255, 255, 255, 0.75)';
  for (const [i] of snowflakes.entries()) {
    ctx.beginPath();
    ctx.arc(snowflakes[i].x, snowflakes[i].y++, snowflakes[i].size, 0, Math.PI * 2);
    ctx.fill();

    // 화면을 넘어가면 삭제한다.
    if (snowflakes[i].y > ctxH) {
      snowflakes.splice(i, 1);
    }
  }
}

// 매 시간 화면을 갱신한다.
function animate() {
  ctx.clearRect(0, 0, ctxW, ctxH);
  ctx.drawImage(bgImage, 0, 0);
  snow();
  requestAnimationFrame(animate);
}

눈송이 낙하 속도를 조정하여 사실적으로 보이게 하기

05.gif

const snowflakes = [];

/// 눈송이를 추가한다.
function addSnowflake() {
  // x 좌표를 랜덤으로 변경한다.
  let x = Math.floor(Math.random() * ctxW) + 1;
  let y = 0;
  // 눈송이의 크기를 랜덤으로 변경한다.
  const size = Math.floor(Math.random() * 3) + 1;

  snowflakes.push({ x, y, size });
}

// 눈송이를 그린다.
function snow() {
  addSnowflake();

  ctx.fillStyle = 'rgba(255, 255, 255, 0.75)';
  for (const [i] of snowflakes.entries()) {
    ctx.beginPath();
    // 눈송이가 떨어지는 속도를 눈송이의 크기 값에 비례해서 계산
    const ty = snowflakes[i].y += snowflakes[i].size * 0.5;
    ctx.arc(snowflakes[i].x, ty, snowflakes[i].size * 0.5, 0, Math.PI * 2);
    ctx.fill();

    // 화면을 넘어가면 삭제한다.
    if (snowflakes[i].y > ctxH) {
      snowflakes.splice(i, 1);
    }
  }
}

// 눈송이의 개수를 화면에 표시한다.
function displayCount() {
  ctx.fillStyle = 'white';
  ctx.font = 'bold 14px Arial, sans-serif';
  ctx.fillText(snowflakes.length, 10, 20);
}

// 매 시간 화면을 갱신한다.
function animate() {
  ctx.clearRect(0, 0, ctxW, ctxH);
  ctx.drawImage(bgImage, 0, 0);
  snow();
  displayCount();
  requestAnimationFrame(animate);
}

바람이 불면 옆으로 기울여서 눈송이가 날리는 효과 만들기

06.gif

const ctxW = canvas.width + 100;
const ctxH = canvas.height + 100;

const bgImage = new Image();
bgImage.src = '/winternight.jpg';

const snowflakes = [];

/// 눈송이를 추가한다.
function addSnowflake() {
  // x 좌표를 랜덤으로 변경한다.
  let x = Math.floor(Math.random() * ctxW) - 100;
  let y = 0;
  // 눈송이의 크기를 랜덤으로 변경한다.
  const size = Math.floor(Math.random() * 3) + 1;

  snowflakes.push({ x, y, size });
}

// 눈송이를 그린다.
function snow() {
  addSnowflake();

  ctx.fillStyle = 'rgba(255, 255, 255, 0.75)';
  for (const [i] of snowflakes.entries()) {
    ctx.beginPath();
    const ty = snowflakes[i].y += snowflakes[i].size * 0.5;
    ctx.arc(snowflakes[i].x, ty, snowflakes[i].size * 0.5, 0, Math.PI * 2);
    ctx.fill();

    // 화면을 넘어가면 삭제한다.
    if (snowflakes[i].y > ctxH) {
      snowflakes.splice(i, 1);
    }
  }
}

// 눈송이의 개수를 화면에 표시한다.
function displayCount() {
  ctx.fillStyle = 'white';
  ctx.font = 'bold 14px Arial, sans-serif';
  ctx.fillText(snowflakes.length, 10, 20);
}

// 매 시간 화면을 갱신한다.
function animate() {
  ctx.save();
  ctx.clearRect(0, 0, ctxW, ctxH);
  ctx.drawImage(bgImage, 0, 0);
  displayCount();
  // 배경을 그린 다음에 rotate()를 이용해서 눈송이만 회전한다.
  ctx.rotate(-0.2);
  snow();
  ctx.restore();
  requestAnimationFrame(animate);
}