[Project] Subclass Dance Party: Snowy Landscape

Ha Young Do·2021년 4월 20일
0
post-thumbnail

Subclass Dance Party 프로젝트의 기본적인 스펙은, class 문법을 이용하여 춤추는 (반짝이는) dancer들을 화면에 생성하는 것이었다. OOP의 상속 및 다형성 특징을 이용하여, 기본적으로 화면에 점들을 생성하는 Dancer 클래스와, Dancer로부터 속성과 메소드를 상속받아 생성된 자리에서 반짝이는 BlinkyDancer 클래스를 구현하였다.

(🔼 add a blinky dancer 버튼을 누르면 제자리에서 특정 interval을 가지고 반짝이는 BlinkyDancer들이 화면에 추가된다.)

이후 추가적인 기능 구현 및 CSS는 페어와 함께 자유롭게 컨셉을 구상하여 만들어 보게 되었다. 페어분이 먼저 제자리에서만 반짝이는 dancer가 아니라 위치를 이동하는 dancer를 만들어 보자는 아이디어를 내셔서, 왼쪽 아래 대각선으로 내려오며 춤추는 클래스를 구현해 보았다.

class DancerClass2 extends DancerClass {
    step () {
      super.step();
      let style = this.$node.style;
      let distanceFromTop = parseFloat(style.top.slice(0, -2));
      let distanceFromLeft = parseFloat(style.left.slice(0, -2));

      if (distanceFromTop < document.body.clientHeight - 50 && 50 < distanceFromLeft) {
        style.top = `${distanceFromTop + 10}px`
        style.left = `${distanceFromLeft - 30}px`;
        style.display = 'inline-block';
      } else {
        style.top = `${document.body.clientHeight - 50}px`;
        style.left = '50px';
        style.display = 'none';
      }
    }
  }

DancerClass의 step() 메소드가 이미 setTimeout을 통해서 interval을 두고 반복되게 설계되어 있다는 점에 착안하여, step() 메소드가 호출될 때마다 위치값을 아래쪽으로 10px, 왼쪽으로 30px 업데이트 하도록 만들었다. 만약 좌측 혹은 하단의 벽에 부딫힐 경우 display를 none으로 업데이트 하여 보이지 않게 된다.

대각선 아래쪽으로 움직이는 dancer들을 보니 꼭 비 혹은 눈 같다는 생각이 들어 내가 snowflake concept를 제안하게 되었고, 서로 다르게 움직이는 두 개의 SnowflakeDancer 클래스를 만들었다.

let leftOrRight = true;
class SnowflakeDancer1 extends DancerClass {
    step () {
      super.step();
      let style = this.$node.style;
      let distanceFromTop = parseFloat(style.top.slice(0, -2));
      let distanceFromLeft = parseFloat(style.left.slice(0, -2));

      if (distanceFromTop < 100) {
        style.opacity = distanceFromTop / 100;
      } else {
        style.opacity = 1;
      }

      if (distanceFromTop < document.body.clientHeight - 50) {
        style.top = `${distanceFromTop + 10}px`
        style.left = leftOrRight === true ? `${distanceFromLeft - 30}px` : `${distanceFromLeft + 30}px`;
        leftOrRight = leftOrRight === true ? false : true;
      } else {
        style.top = `${document.body.clientHeight - 50}px`;
      }
    }
}

SnowflakeDancer1은 한 방향으로 흐르는 것이 아니라 화면 상단에서부터 흔들리며 내려오는 눈꽃 기본형 클래스이다. leftOrRight 변수를 이용해 step() 메소드가 호출될 때마다 위치값을 왼쪽 아래 혹은 오른쪽 아래로 업데이트 하도록 만들었다. 보는 재미를 위해 opacity도 0에서 시작하여 내려올수록 더 선명해지도록 설계하였다.

(🔼 add a snowflake 버튼을 누르면 화면 상단에서부터 흔들리며 내려오는 snowflake들이 화면에 추가된다.)

SnowflakeDancer2는 DancerClass2에서 구현해 본 것처럼, 왼쪽 아래로 흐르는 눈꽃 클래스이다. 한쪽 방향으로 흐르도록 구현하고 보니, 바람이 부는 것처럼 보인다는 생각이 들어 add wind 버튼을 추가해, 버튼을 누르면 아래로만 내려오던 SnowflakeDancer1들이 SnowflakeDancer2로 교체되도록 하였다. 이를 위해 add wind 버튼에 연결해 줄 addWind() 함수를 만들었다.

function addWind() {
  while (document.body.children.length > 2) {
    document.body.removeChild(document.body.lastChild);
  }

  let newDancers = []

  for (let i = 0; i < dancers.length; i++) {
    let top = dancers[i].$node.style.top;
    let left = dancers[i].$node.style.left;
    let newDancer = new SnowflakeDancer2(parseInt(top.slice(0, -2)), parseInt(left.slice(0, -2)), dancers[i].timeBetweenSteps);
    newDancers.push(newDancer);
  }

  dancers = newDancers;

  dancers.forEach(dancer => {
    document.body.appendChild(dancer.$node);
  })
}

addWind() 함수가 실행이 되면, 현재 만들어진 SnowflakeDancer1 element들이 모두 삭제되고, 삭제된 순간의 같은 위치값을 가진 SnowflakeDancer2들로 대체된다.

(🔼 화면에 눈이 오는 상태에서 add wind 버튼을 누르면 좌향풍이 추가되어 snowflake들이 왼쪽 아래로 흐른다.)

마지막으로 구현할 수 있는 advanced 과제 중, css transition을 응용해 보라는 과제가 있어 마지막 기능을 추가하였다. 화면 왼쪽 상단에 태양 이미지를 숨겨 놓고, 태양 이미지 위에 커서를 hover하면 해가 나오면서 눈이 녹도록 만들었다.

function makeSunny() {
  document.body.classList.add('sunny');
  while (document.body.children.length > 2) {
    document.body.removeChild(document.body.lastChild);
  }
}

const sun = document.querySelector('.sun');
sun.addEventListener('transitionend', makeSunny);

태양 element 위에 커서가 hover되면 css transition 효과로 태양의 크기가 커진다. transition이 끝난 순간 makeSunny() 함수가 실행이 되면 css로 배경 이미지가 변하고, 현재 만들어진 눈꽃 element들이 모두 삭제된다.

(🔼 왼쪽 상단으로 커서를 가져가면 태양이 나오면서 눈은 모두 녹고 봄이 된다.)

아쉬운 점: add wind를 눌러 SnowflakeDancer1에서 SnowflakeDancer2로 교체해줄 때 자연스럽게 변화하는 것이 아니라 시간이 뜨면서 모든 눈꽃이 사라졌다가 나타나는 것이 육안으로 보이는 현상이 일어난다. 두 개의 다른 class가 아니라, 하나의 class에 서로 다른 움직임 메소드를 구현해 주는 것이 더 적합했을 수도 있겠다.

profile
Codestates Software Engineering Full IM 28th

0개의 댓글

관련 채용 정보