falling snowflake effect js - 눈송이 배치

HTML 2025. 3. 27. 22:23

 

이전 글 : https://manualbook.tistory.com/128

 

falling snowflake effect js - 프로젝트 폴더 구성 및 기본 코드

눈이 떨어지는 애니메이션 효과를 구현해보고 싶다. vite + 바닐라 js조합으로 프로젝트를 구성하고 클래스 문법을 사용하여 눈송이가 떨어지는 효과를 구현해본다. main.jsimport "./style.css";import {

manualbook.tistory.com

 

 

이전 글에서 canvas에 이미지를 그려서 눈송이를 표시하는 방식에서 img 태그로 눈송이를 출력하고 이를 div 태그에 추가하는 방식으로 변경해 봤다.

 

main.js

import "./style.css";
import { Manager } from "./manager";

function mainCanvas() {
  const canvas = document.createElement("canvas");
  const app = document.querySelector("#app");

  app.append(canvas);

  const ctx = canvas.getContext("2d");
  const manager = new Manager(ctx);

  manager.draw();
}

function mainImage() {
  const div = document.createElement("div");
  const snows = [];

  init(div, 100, snows);
}

mainImage();

function init(el, numOfSnow, snows) {
  el.className = "layout-snow";

  const app = document.querySelector("#app");

  app.append(el);

  for (let i = 0; i < numOfSnow; i++) {
    const s = createSnow(getRandomSize(20, 30));

    snows.push(s);

    el.append(s);
  }
}

function getRandom(min, max) {
  return Math.random() * (max - min) + min;
}

function getRandomSize(minSize, maxSize) {
  return getRandom(minSize, maxSize);
}

function createSnow(size) {
  const img = document.createElement("img");

  img.src = "snowflake.svg";

  img.style.width = size + "px";
  img.style.height = size + "px";

  const innerWidth = window.innerWidth;
  const innerHeight = window.innerHeight;

  img.style.top = getRandom(0, innerWidth) + "px";
  img.style.left = getRandom(0, innerHeight) + "px";

  img.classList.add("snow");

  return img;
}

 

 

이전 canvas를 사용한 코드는 mainCanvas로 구현하고 이번에 이미지 태그로 구현한 부분은 mainImg로 구분했다.

 

css로는 주로 변하지 않는 스타일 요소를 설정해 두고, js로는 랜덤 한 위치나 사이즈를 설정했다.

 

 

style.css

body {
  margin: 0;
  padding: 0;
}

#app {
  width: 100vw;
  height: 100vh;
}

canvas {
  display: block;

  width: 100%;
  height: 100%;
}

.layout-snow {
  position: relative;

  width: 100vw;
  height: 100vh;

  background: blue;
}

.snow {
  position: absolute;
  filter: invert(100%) sepia(5%) saturate(0%) hue-rotate(319deg)
    brightness(105%) contrast(105%);

  animation: spinning-snow 3s infinite;
  animation-timing-function: linear;
}

@keyframes spinning-snow {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}