본문 바로가기

Front-end/Design

Bouncing Logo Screen Saver 만들기

화면 모서리에 부딪히면 bounce하는 png 이미지를 js로 구현해 페이지에 디자인 요소를 추가하고 싶었다.

기술 포스팅에 적절하진 않은 같지만 KPT 회고 방법론을 사용해 볼 것이다.

💡 KEEP

1. 구글링 키워드를 잘 이용했다. (Bouncing, screen saver, js)

 

2. 잘 정리된 설명을 바탕으로 원하는 애니메이션을 구현할 수 있었다. 

 

https://dev.to/s1mpson/creating-bouncing-logo-with-javascript-4ekg

 

Creating a Bouncing Logo with JavaScript ⛹🏽‍♀️

So, recently I've seen a YouTube video about DVD bouncing logo and thought, why not create one using...

dev.to


💡 구현

1. HTML

<div class="fly ironman"></div>

 

- 내 html 파일의 body는 header, main, footer로 구분되어 있었다.

 

- 이미지가 body에 부딪혔을 때 bounce되어야 하므로 footer 아래에 코드를 작성하였다.

2. CSS

.fly {
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
  width: 80px;
  height: 80px;
  position: fixed;
  left: calc(50vw - 40px);
  top: calc(50vw - 40px);
  z-index: 200;
}

.fly.ironman {
  background-image: url("../images/dh/ironman/fly.png");
}
.fly.spiderman {
  background-image: url("../images/dh/spiderman/fly.png");
}
.fly.dr-strange {
  background-image: url("../images/dh/dr-strange/fly.png");
}

 

- 이미지 div의 크기를 적용하고, background 속성에 알맞은 값을 준다.

 

- 스크롤을 따라 이동할 것이므로 position을 fixed로 설정한 후 초기 위치를 화면 중앙으로 설정한다.

3. JAVASCRIPT

const body = document.querySelector("body");
const hero = document.querySelector(".fly");
let FPS = 60;

let width,
  height,
  velocityX = 1,
  velocityY = 1,
  pause = true;

 

- FPS:  setInterval 함수의 실행 간격을 조절

 

- width, height: 스크린 사이즈

 

- velocity: 이미지 이동 속도

 

- pause: 이미지의 이동을 정지하는 flag

const reset = () => {
  width = window.innerWidth;
  height = window.innerHeight;

  pause =
    width <= hero.getBoundingClientRect().width ||
    height <= hero.getBoundingClientRect().height;

  hero.style.left = "calc(50vw - 40px)";
  hero.style.top = "calc(50vh - 40px)";
};

reset();

window.addEventListener("resize", reset);

 

- reset 함수는 window resize시에 실행된다. 

 

- width와 height에 window 사이즈를 받아 이미지 보다 페이지 사이즈가 작아지면 pause는 true가 된다.

 

- 그 후 이미지를 초기 위치로 이동한다.

setInterval(() => {
  if (pause) return;

  let rect = hero.getBoundingClientRect();
  let left = rect.x;
  let top = rect.y;

  if (left + rect.width >= width || left <= 0) {
    velocityX = -velocityX;
  }

  if (top + rect.height >= height || top <= 0) {
    velocityY = -velocityY;
  }

  hero.style.left = rect.x + velocityX + "px";
  hero.style.top = rect.y + velocityY + "px";
  if (isHeroCaught) {
    pause = true;
    if (hero.classList.contains("ironman")) {
      hero.style.backgroundImage = "url('../../images/dh/ironman/fly2.png')";
    } else if (hero.classList.contains("spiderman")) {
      hero.style.backgroundImage = "url('../../images/dh/spiderman/fly2.png')";
    } else if (hero.classList.contains("dr-strange")) {
      hero.style.backgroundImage = "url('../../images/dh/dr-strange/fly2.png')";
    }
  }
}, 1000 / FPS);

 

- 이미지의 left border의 스크린 상 위치를 left, top border의 위치를 top으로 계산한다.

 

- left와 이미지의 너비 합 (right border의 스크린 상 위치)이 페이지 가로 사이즈를 넘어가거나

 

- left가 0보다 작아지면 (페이지 왼쪽 벽에 부딪히면) 이미지의 x축 이동 방향을 바꾼다.

 

- 같은 방법을 y축 이동 방향에도 적용한다.

 

- 이미지의 left와 top값에 현재 위치와 이동 방향을 더한 값을 적용한다.

 

- isHeroCaught flag 작동 시 이미지 소스를 바꾼다.

 

- 해당 함수는 1000 / FPS (1초에 fps번) 마다 실행한다.

let isHeroCaught = false;
hero.addEventListener("mouseover", () => {
  isHeroCaught = true;
});
hero.addEventListener("mouseout", () => {
  isHeroCaught = false;
  pause = false;
  if (hero.classList.contains("ironman")) {
    hero.style.backgroundImage = "url('../../images/dh/ironman/fly.png')";
  } else if (hero.classList.contains("spiderman")) {
    hero.style.backgroundImage = "url('../../images/dh/spiderman/fly.png')";
  } else if (hero.classList.contains("dr-strange")) {
    hero.style.backgroundImage = "url('../../images/dh/dr-strange/fly.png')";
  }
});

 

- 이미지에 mouseover시 isHeroCaught flag를 true로 바꾼다.

 

- mouseout 시 이미지소스를 원래대로 바꾼다.


🤔 PROBLEM

1. 이미지의 해상도가 높아 로딩이 필요하다.

 

2. Github 호스팅 페이지에서 이미지의 경로 이슈가 있었다.

 

3. Moblie 버전에서 이미지가 상, 하단에 도착 직후 스크롤 시 화면 바깥으로 나간 것으로 인식되어 reset이 실행되는 작은 버그가 발생한다.


🚀 TRY

호스팅 서버에서의 버그를 제외하면 의도대로 동작했다?

 

다른 환경에서 실행해보자.

'Front-end > Design' 카테고리의 다른 글

히어로 등장 애니메이션  (0) 2024.02.04
Hero select 디자인 구현  (0) 2024.02.04