groupEffect로 StarField만들기

gu·2023년 8월 4일
0

Web Animation

목록 보기
7/7

💻 StarField

Web Animation Api로 groupEffect를 사용하여 날라오는 3D로 날라오는 별들 star field를 구현해보자.

🖤 Output


클릭하면 animation이 일시정지되고 다시 클릭하면 곧이어 animation이 다시 실행된다.

🖤 구현코드

이번 animation을 구현하기위해 04.htmlStar.js 두파일이 사용되었다.

  • 04.html
<head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Starfield</title>
        <style>
            body {
                overflow: hidden;
                background-color: black;
            }

            .star {
                position: absolute;
                width: 3px;
                height: 3px;
                font-size: 0;
                border-radius: 50%;
                background: white;
            }
        </style>
</head>

어두운 우주에 흰색 별이 날라오는 것처럼 구현하기위해 body전제는 background-color를 블랙으로 줬고 star는 흰색을 주었다. body부분의 코드는 아래와같다.

<body>
        <!-- groupEffect를 사용하기위해 가져온 cdn--> 
        <script src="https://cdnjs.cloudflare.com/ajax/libs/web-animations/2.3.2/web-animations-next.min.js"></script>
        <script type="module">
            import Star from "./Star.js";
			
          // 날라가는 별이 200개 
            const numberOfStars = 200;

            const effects = [];
          // 3D효과로보이기위해 x,y,z값이 필요하다. 
            let x, y, z;
           // Z좌표값이 비율로 적용되게끔하기위해
            let scale;
            let keyframes, options;
            let star;
            let pointFrom, pointTo;
            let width = window.innerWidth;
            let height = window.innerHeight;
            const zModifier = height;
            function set3DPoint(ax, y, z) {
                const scale = zModifier / (zModifier + z);
                const x2D = x * scale + width * 0.5;
                const y2D = y * scale + height * 0.5;

                return [x2D, y2D, scale];
            }
            for (let i = 0; i < numberOfStars; i++) {
                x = Math.random() * width - width * 0.5;
                y = Math.random() * height - height * 0.5;
                z = Math.random() * zModifier;
                scale = zModifier / (zModifier + z);

                // 애니메이션에서 from에 해당되는 변수(시작점)
                pointFrom = set3DPoint(x, y, z);
                // 애니메이션에서 to에 해당되는 변수(도착점)
                // zModifier을 빼준이유가 z값의 차를 만들기위함이다.
                pointTo = set3DPoint(x, y, z - zModifier);

                star = new Star(i);
                keyframes = [
                    {
                        transform: `
            			translate(${pointFrom[0]}px, ${pointFrom[1]}px)
            			scale(${pointFrom[2]})
            		`,
                    },
                    {
                        transform: `
            			translate(${pointTo[0]}px, ${pointTo[1]}px)
            			scale(${pointTo[2]})
            		`,
                    },
                ];
                options = {
                    // 속도조정 분자값이 클수록 별이 천천히 움직임
                    duration: 500 / scale,
                    iterations: Infinity,
                    fill: "both",
                    easing: "linear",
                };

                effects.push(new KeyframeEffect(star.element, keyframes, options));
            }
            const groupEffect = new GroupEffect(effects);
            const animation = document.timeline.play(groupEffect);
            console.log(animation);
		
        // 창을 클릭하면 ani가 멈췄다가 다시클릭하면 그대로 다시 시작하도록하는 이벤트 
            window.addEventListener("click", () => {
                if (animation.playState === "paused") {
                    animation.play();
                } else {
                    animation.pause();
                }
            });
        </script>
    </body>

✔ script 타입을 모듈로 지정한 이유

- Star파일을 따로 스크립트로 만들어서 임포트하기 위해
- 모듈타입으로 스크립트를 만들었을 때 변수를 선언하면 자체적으로 스코프가 되서 접근이 불가하다. 
(원래 자바스크립트에서는 전역변수를 사용하지 않는 것이 좋다.)
  • Star.js
export default class Star {
    constructor(num) {
        this.element = document.createElement("div");
        this.element.classList.add("star");
        this.element.innerHTML = num;
        document.body.append(this.element);
    }
}

참고

인프런-1분코딩

0개의 댓글