[javaScript] 카운트 다운 만들기 + 숫자 올라가는 애니메이션 만들기

김보나·2022년 7월 21일
0

javascript

목록 보기
7/12
post-thumbnail

디자인 팀에서 카페 24 메인 배너에 달 카운트 다운 타이머를 만들어 달라고 하셨다.

요구사항

  1. 메인 타이머에 일/시/분/초 표시
  2. 작은 타이머에 일/시/분 표시
  3. 날짜 커스텀이 가능할 것
  4. 기타 디자인 커스텀이 가능 할 것

html

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="timer.css" />
    <title>Document</title>
  </head>

  <body>
    <!-- 메인 타이머 -->
    <div class="timer-background" >
        <p id="timer-main-title">D-DAY</p>
            <div class="timer-box">

                <span class="timer-component">
                <p id="timer-days" class="timer-title" >-</p>
                <p class="timer-sub-title"></p>
                </span>
                
                <p class="timer-colon">:</p>
                
                <span class="timer-component">
                <p id="timer-hours" class="timer-title" >-</p>
                <p class="timer-sub-title">시간</p>
                </span>
                
                <p class="timer-colon">:</p>
                
                
                <span class="timer-component">
                <p id="timer-minute" class="timer-title" >-</p>
                <p class="timer-sub-title"></p>
                </span>
                
                <p class="timer-colon">:</p>
                
                <span class="timer-component">
                <p id="timer-seconds" class="timer-title">-</p>
                <p class="timer-sub-title"></p>
                </span>
                
            </div>
<!-- 작은 타이머 -->
    <div class="narrow-timer-background" id="narrow-timer-background">
      <p class="narrow-timer-title">
        D-DAY
        <span class="narrow-timer-time">
          <span> </span>
          <span id="narrow-timer-days">-</span><span id="narrow-timer-hours">-</span>시간
          <span id="narrow-timer-minute">-</span><span id="narrow-timer-seconds">-</span></span>
      </p>
    </div>
    <script src="timer.js"></script>
  </body>
</html>
  • 클래스 명으로 CSS 디자인을 적용시켜주었다.
  • 원래는 시간을 나타내는 숫자에는 같은 ID를 사용했다가 구조상의 문제로 다 각각 만들어주었다.
  • 두개를 한페이지에 한번에 사용하지 않는다면 id를 공통으로 줘도 작동한다.(같이 사용한다하면 js에서 querySelectorAll을 사용하면 되긴한다.)
  • 시작시에는 -에서 시작 되도록 만들었다.

CSS

.timer-background {
  width: 100%;
  height: 124px;
  /*  백그라운드 색 코드를 아래 background-color에 넣어주시면 됩니다 */
  background-color: #399bfe;
  text-align: center;
  font-size: 16px;
  font-weight: 500;

  /* 타이머 부분을 없애고 싶다면 아래 코드의 앞 뒤 /*표시(주석)을 지워주시면됩니다. */
  /* display: none; */
}

#timer-main-title {
  padding-top: 14px;
  font-weight: 500;
  font-size: 16px;
  line-height: 16px;
  padding: 0;
  margin: 0;
  padding-top: 10px;
  padding-bottom: 14px;
  align-content: flex-start;
}

.timer-box {
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}

.timer-component {
  width: 50px;
  height: 64px;
  border-color: #333333;
  border-radius: 4px;
  margin-bottom: 16px;
}

/*메인 타이머의 제목 색을 변경할 경우 color를 바꾸시면 됩니다. */
.timer-title {
  font-weight: 700;
  font-size: 28px;
  line-height: 28px;
  color: #ffffff;
  margin: 0;
  padding: 0;
  margin-top: 12px;
  margin-bottom: 4px;
}

/*메인 타이머의 숫자 색을 변경할 경우 color를 바꾸시면 됩니다.*/
.timer-sub-title {
  font-weight: 400;
  font-size: 10px;
  color: #ffffff;
  margin: 0;
  padding: 0;
}

/*타이머 콜론 색을 변경할 경우 color의 색을 변경하면 됩니다.*/
.timer-colon {
  font-weight: 700;
  font-size: 32px;
  color: #333333;
  padding: 0;
  margin: 8px;
  height: 64px;
}

/* 좁은 타이머의 배경 색을 변경할 경우 아래의 background의 색 코드를 바꾸면 됩니다. */
.narrow-timer-background {
  background: #399bfe;
  width: 100%;
  height: 46px;
  display: block;
}
/* 좁은 타이머의 제목 색을 변경할 경우 아래의 background의 색 코드를 바꾸면 됩니다. */
.narrow-timer-title {
  font-style: normal;
  font-weight: 400;
  font-size: 14px;
  line-height: 14px;
  text-align: center;
  color: #333333;
  padding-top: 16px;
  padding-bottom: 16px;
}

.narrow-timer-time {
  font-weight: 700;
  padding: 0;
}
  • 디자이너 분이 보시는것이여서 CSS 코드마다 주석을 달아놓았다.
  • 색을 변수로 만들어서 넣을걸! 이라는 생각이 방금 포스팅을 하면서 떠올랐다.

javaScript

const dateString = "2022/07/30 15:55:00";

let days;
let hours;
let minutes;
let sec;

const $counter = document.querySelector(".count");
const $day = document.getElementById("timer-days");
const $hour = document.getElementById("timer-hours");
const $minute = document.getElementById("timer-minute");
const $second = document.getElementById("timer-seconds");

const $narrowDay = document.getElementById("narrow-timer-days");
const $narrowHours = document.getElementById("narrow-timer-hours");
const $narrowMinutes = document.getElementById("narrow-timer-minute");
const $narrowSecond = document.getElementById("narrow-timer-seconds");

const $narrowTimer = document.getElementById("narrow-timer-background");

const setZero = numbers => {
  if (numbers.toString().length < 2) {
    return "0" + numbers.toString();
  }
  return numbers;
};

function millisecondToDate(ms) {
  days = setZero(Math.floor(ms / (24 * 60 * 60 * 1000)));
  let daysms = ms % (24 * 60 * 60 * 1000);
  hours = setZero(Math.floor(daysms / (60 * 60 * 1000)));
  let hoursms = ms % (60 * 60 * 1000);
  minutes = setZero(Math.floor(hoursms / (60 * 1000)));
  let minutesms = ms % (60 * 1000);
  sec = setZero(Math.floor(minutesms / 1000));
}
setTimes();

function setTimes() {
  let now = new Date();
  let finishDate = new Date(dateString).getTime() + 9 * 60 * 60 * 1000;
  let today = now.getTime() + 9 * 60 * 60 * 1000;
  let diffDate = finishDate - today;
  millisecondToDate(diffDate);
}

function setTimerElement() {
  $day.innerHTML = days;
  $hour.innerHTML = hours;
  $minute.innerHTML = minutes;
  $second.innerHTML = sec;
}

function setNarrowTimerElement() {
  $narrowDay.innerHTML = days;
  $narrowHours.innerHTML = hours;
  $narrowMinutes.innerHTML = minutes;
  $narrowSecond.innerHTML = sec;
}

let isMain = true;
setTimes();

const counter = ($counter, max) => {
  if (max < 10) {
    max = max * 10;
  }
  let now = max;

  const handle = setInterval(() => {
    $counter.innerHTML = Math.ceil(max - now);

    if (now < 3) {
      clearInterval(handle);
      const count = setInterval(() => {
        setTimes();
        if (isMain) {
          setTimerElement();
        } else {
          setNarrowTimerElement();
        }
        setNarrowTimerElement();
      }, 1000);
    }

    const step = now / 10;

    now -= step;
  }, 50);
};

window.onload = () => {
  if (isMain) {
    setTimeout(() => counter($day, days), 500);
    setTimeout(() => counter($hour, hours), 500);
    setTimeout(() => counter($minute, minutes), 500);
    setTimeout(() => counter($second, sec), 500);
  } else {
    setTimeout(() => counter($narrowDay, days), 500);
    setTimeout(() => counter($narrowHours, hours), 500);
    setTimeout(() => counter($narrowMinutes, minutes), 500);
  }
};

function isMainScreen(element) {
  isMain = true;
  let nowAdress = window.location.href.toString();

  if (
    nowAdress == "http://127.0.0.1:5500/" ||
    nowAdress == "http://127.0.0.1:5500/index.html"
  ) {
    // element.style.display = "none";
  } else {
    isMain = false;
  }
}

isMainScreen($narrowTimer);



날짜 설정 및 html 요소 선택

const dateString = "2022/07/30 18:55:00";

let days;
let hours;
let minutes;
let sec;

const $counter = document.querySelector(".count");
const $day = document.getElementById("timer-days");
const $hour = document.getElementById("timer-hours");
const $minute = document.getElementById("timer-minute");
const $second = document.getElementById("timer-seconds");

const $narrowDay = document.getElementById("narrow-timer-days");
const $narrowHours = document.getElementById("narrow-timer-hours");
const $narrowMinutes = document.getElementById("narrow-timer-minute");
const $narrowSecond = document.getElementById("narrow-timer-seconds");

const $narrowTimer = document.getElementById("narrow-timer-background");
  • id를 공통으로 사용하지 못하게 되어서 엄청나게 많이 요소를 불러왔다.
  • 날짜 형식은 String으로, 저 형식을 따른다면 사파리에서도 정상적으로 동작하므로 크로스 브라우징이 가능하다.
  • 마지막 요소는 메인 화면에서는 작은 화면의 display 속성을 none으로 바꾸려고 가져온 요소이다.

남은 시간 계산하기

const setZero = numbers => {
  if (numbers.toString().length < 2) {
    return "0" + numbers.toString();
  }
  return numbers;
};

function millisecondToDate(ms) {
  days = setZero(Math.floor(ms / (24 * 60 * 60 * 1000)));
  let daysms = ms % (24 * 60 * 60 * 1000);
  hours = setZero(Math.floor(daysms / (60 * 60 * 1000)));
  let hoursms = ms % (60 * 60 * 1000);
  minutes = setZero(Math.floor(hoursms / (60 * 1000)));
  let minutesms = ms % (60 * 1000);
  sec = setZero(Math.floor(minutesms / 1000));
}
setTimes();

function setTimes() {
  let now = new Date();
  let finishDate = new Date(dateString).getTime() + 9 * 60 * 60 * 1000;
  let today = now.getTime() + 9 * 60 * 60 * 1000;
  let diffDate = finishDate - today;
  millisecondToDate(diffDate);
}

function setTimerElement() {
  $day.innerHTML = days;
  $hour.innerHTML = hours;
  $minute.innerHTML = minutes;
  $second.innerHTML = sec;
}

function setNarrowTimerElement() {
  $narrowDay.innerHTML = days;
  $narrowHours.innerHTML = hours;
  $narrowMinutes.innerHTML = minutes;
  $narrowSecond.innerHTML = sec;
}
  • setZero는 숫자 앞에 0을 붙여주는 함수다.
  • millisecondToDate는 밀리세컨드로 계산한 남은 날짜를 일/시/분/초에 맞게 변환해주는 메소드다.
  • setTimes는 현재날짜에서 타겟날짜의 밀리세컨드로 계산해주는 메소드이다. 여기서 millisecondToDate를 호출한다.
  • setTimerElementsetNarrowTimerElement는 html 각각의 요소에 변화를 준다.
  • 화면이 어딘지에 따라서 요소가 다르기 때문에 메인타이머와 작은 타이머를 나누었다.

애니메이션 효과

const counter = ($counter, max) => {
  if (max < 10) {
    max = max * 10;
  }
  let now = max;

  const handle = setInterval(() => {
    $counter.innerHTML = Math.ceil(max - now);

    if (now < 3) {
      clearInterval(handle);
      const count = setInterval(() => {
        setTimes();
        if (isMain) {
          setTimerElement();
        } else {
          setNarrowTimerElement();
        }
        setNarrowTimerElement();
      }, 1000);
    }

    const step = now / 10;

    now -= step;
  }, 50);
};
  • setInterval을 사용하여 0.5초에 한번씩 숫자가 증가하도록 만들었다.
  • 남은 시간이 10보다 적으면 숫자가 올라가는 효과가 어색해서 숫자를 임의로 늘렸다.
  • 숫자가 끝까지 올라갔다면(now가 3 미만으로 남았다면), 디데이 숫자를 1초마다 불러오게 했다.
  • clearInterval을 사용하여 0.5초마다 불러온 함수는 사라지게 했다.

메인 화면 판단 로직

function isMainScreen(element) {
  isMain = true;
  let nowAdress = window.location.href.toString();

  if (
    nowAdress == "http://127.0.0.1:5500/" ||
    nowAdress == "http://127.0.0.1:5500/index.html"
  ) {
    element.style.display = "none";
  } else {
    isMain = false;
  }
}

isMainScreen($narrowTimer);

  • 먼저 처음에 들어가는 페이지는 메인화면이므로 디폴트값으로 true를 주었다.
  • window.location.href에 있는 url이 내가 설정해준 string과 같다면 작은 타이머의 display 속성을 none으로 바꿔서 타이머가 안보이게 만들었다.

실행 로직

window.onload = () => {
  if (isMain) {
    setTimeout(() => counter($day, days), 500);
    setTimeout(() => counter($hour, hours), 500);
    setTimeout(() => counter($minute, minutes), 500);
    setTimeout(() => counter($second, sec), 500);
  } else {
    setTimeout(() => counter($narrowDay, days), 500);
    setTimeout(() => counter($narrowHours, hours), 500);
    setTimeout(() => counter($narrowMinutes, minutes), 500);
  }
};
  • 자바스크립트가 시작되면 해당 로직을 바로 실행하게 했다.

전체 코드는 여기서 확인할 수 있다.

profile
우주최강 개발자가 될 때까지😈

0개의 댓글