JS 달력 만들기

히치키치·2021년 11월 3일
1
post-thumbnail

STEP

  1. HTML 뼈대 잡기
  2. 날짜 가져오기
  3. 스타일 입히기
  4. 날짜 이동/구분 & Today

HTML 뼈대 잡기


1. 현재 년도 & 월
2. 좌우 이동 화살표 - 이전/다음 달 이동
3. 가장 윗 줄은 요일
4. 일요일은 빨간색, 토요일은 파란색 글자, Today는 특별한 색
5. 이전 달, 다음 달 날짜는 반투명

 <div class="calendar">
        <div class="header">
            <div class="year-month"></div>
            <div class="nav">
                <button class="nav-btn go-prev">&lt;</button>
                <button class="nav-btn go-today">Today</button>
                <button class="nav-btn go-next">&gt;</button>
            </div>
        </div>
        <div class="main">
            <div class="days">
                <div class="day"></div>
                <div class="day"></div>
                <div class="day"></div>
                <div class="day"></div>
                <div class="day"></div>
                <div class="day"></div>
                <div class="day"></div>
            </div>
            <div class="dates"></div>
        </div>
    </div>
화면설명
1. <div class="header"><div class="main">로 구분
: header : 현재 달 & 이전/다음 달 이동
: main : 이번 달 날짜
2. <div class="year-month"></div> : 월 변경 되는 부분
3. <div class="nav"><button class="nav-btn go-prev">&lt;</button><button class="nav-btn go-today">Today</button><button class="nav-btn go-next">&gt;</button></div>
: 좌우 화살표 < >를 통한 이전 달, 다음 달 이동

날짜 가져오기

  1. Date()를 이용해 날짜 데이터 받아오기
const date = new Date();
const viewYear = date.getFullYear();
const viewMonth = date.getMonth();
  1. 년월 표시 : 날짜 데이터로.year-month 채우기
document.querySelector('.year-month').textContent = `${viewYear}년 ${viewMonth + 1}월`;

querySelector 이용해 year-month에 접근해 연도와 월 채우기

  1. 이전달/다음달 날짜 가져오기
  • 지난달 마지막 날짜와 요일
    지난달 날짜 중 몇 개 표시할지 결정
    Date()에 파라미터 0을 전달해 지난 달의 마지막 날 객체 생성
  • 이번달 마지막 날짜와 요일
    다음달 날짜 중 몇 개 표시할지 결정
    다음 달의 0번째 날짜를 뽑아 이번달의 마지막 날 객체 생성
const prevLast = new Date(viewYear, viewMonth, 0);
const thisLast = new Date(viewYear, viewMonth + 1, 0);

const PLDate = prevLast.getDate();
const PLDay = prevLast.getDay();

const TLDate = thisLast.getDate();
const TLDay = thisLast.getDay();
  1. 이전달/다음달 날짜 표시
// 1) 배열 생성
const prevDates = [];
const thisDates = [...Array(TLDate + 1).keys()].slice(1);
const nextDates = [];

// 2) 받아온 날짜를 기준으로 배열에 day 숫자 값을 채워줌
if (PLDay !== 6) {
  for (let i = 0; i < PLDay + 1; i++) {
    prevDates.unshift(PLDate - i);
  }
}

for (let i = 1; i < 7 - TLDay; i++) {
  nextDates.push(i);
}
//3) HTML에 채우기
const dates = prevDates.concat(thisDates, nextDates);

dates.forEach((date, i) => {
  dates[i] = `<div class="date">${date}</div>`;
})

document.querySelector('.dates').innerHTML = dates.join('');
화면1화면2

스타일 입히기

  1. 전체 달력
/*전체 태그의 margin, padding 없애기*/
* {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  box-sizing: border-box;
}

/*달력을 가운데 정렬 : display와 min-height 설정*/
body {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

/*달력의 크기 설정*/
.calendar {
  width: 600px;
  margin: 50px;
  /*margin 통해 브라우저 작아졌을 때 자연스럽게 하기 위해*/
}
  1. header : 이번달 & today & 이전달/다음달 이동
/*header 부분 설정*/
.header {
  display: flex;
  /*header안 year-month와 nav 가로 나열*/
  justify-content: space-between;
  align-items: center;
}

.year-month {
  font-size: 35px;
}

.nav {
  display: flex;
  /*nav 버튼 정렬 위해*/
  border: 1px solid #333333;
  border-radius: 5px;
  /*테두리 그리고 라운딩*/
}

.nav-btn {
  width: 28px;
  height: 30px;
  border: none;
  font-size: 16px;
  line-height: 34px;
  background-color: transparent;
  cursor: pointer;
}

.go-today {
  width: 75px;
  /*today라는 긴 글자 들어가야함으로 너비 크게*/
  border-left: 1px solid #333333;
  border-right: 1px solid #333333;
}
화면

3. main : 요일 & 날짜 & 색깔/투명도 조절
.days {
  display: flex;
  margin: 25px 0 10px;
}

.day {
  width: calc(100% / 7);
  text-align: center;
}

.dates {
  display: flex;
  flex-flow: row wrap;
  height: 500px;
  border-top: 1px solid #333333;
  border-right: 1px solid #333333;
}

.date {
  width: calc(100% / 7);
  padding: 15px;
  text-align: right;
  border-bottom: 1px solid #333333;
  border-left: 1px solid #333333;
}
화면

.day:nth-child(7n + 1),
.date:nth-child(7n + 1) {
  color: #D13E3E;
  /*일요일은 빨간색*/
}

.day:nth-child(7n),
.date:nth-child(7n) {
  color: #396EE2;
  /*토요일은 파란색*/
}
화면

날짜 이동/구분 & Today

  1. 달 이동할 때 달력을 render하기 위해서 함수형태로 js 코드 변경
// Date 객체 생성
const date = new Date();

const renderCalendar = () => {
  const viewYear = date.getFullYear();
  const viewMonth = date.getMonth();

  // year-month 채우기
  document.querySelector('.year-month').textContent = `${viewYear}년 ${viewMonth + 1}월`;

  // 지난 달 마지막 Date, 이번 달 마지막 Date
  const prevLast = new Date(viewYear, viewMonth, 0);
  const thisLast = new Date(viewYear, viewMonth + 1, 0);

  const PLDate = prevLast.getDate();
  const PLDay = prevLast.getDay();

  const TLDate = thisLast.getDate();
  const TLDay = thisLast.getDay();

  // Dates 기본 배열들
  const prevDates = [];
  const thisDates = [...Array(TLDate + 1).keys()].slice(1);
  const nextDates = [];

  // prevDates 계산
  if (PLDay !== 6) {
    for (let i = 0; i < PLDay + 1; i++) {
      prevDates.unshift(PLDate - i);
    }
  }

  // nextDates 계산
  for (let i = 1; i < 7 - TLDay; i++) {
    nextDates.push(i)
  }

  // Dates 합치기
  const dates = prevDates.concat(thisDates, nextDates);

  // Dates 정리
  dates.forEach((date, i) => {
    dates[i] = `<div class="date">${date}</div>`;
  })

  // Dates 그리기
  document.querySelector('.dates').innerHTML = dates.join('');
}

renderCalendar();
  1. 이전달/다음달/Today 이동하는 달 이동 함수
let date = new Date();

goToday 함수에 서 date 값을 재할당해야해서 const가 아닌 let으로 변경

const prevMonth = () => {
  date.setMonth(date.getMonth() - 1);
  renderCalendar();
}

const nextMonth = () => {
  date.setMonth(date.getMonth() + 1);
  renderCalendar();
}

const goToday = () => {
  date = new Date();
  renderCalendar();
}
  1. 좌우 화살표 버튼에 달 이동 함수 클릭 이벤트 부여
  <div class="nav">
    <button class="nav-btn go-prev" onclick="prevMonth()">&lt;</button>
    <button class="nav-btn go-today" onclick="goToday()">Today</button>
    <button class="nav-btn go-next" onclick="nextMonth()">&gt;</button>
  </div>
이전달오늘다음달
  1. 이전달/다음달 날짜들 투명도 조절
  // Dates 정리
  const firstDateIndex = dates.indexOf(1);
  const lastDateIndex = dates.lastIndexOf(TLDate);
  dates.forEach((date, i) => {
    const condition = i >= firstDateIndex && i < lastDateIndex + 1
                      ? 'this'
                      : 'other';

    dates[i] = `<div class="date"><span class="${condition}">${date}</span></div>`;
  })

이전달/다음달 날짜에 CSS 부여하기 위해 HTML 태그 수정

.other {
  opacity: 0.3;
}

투명도 스타일 부여

화면
  1. Today 표시
    // 오늘 날짜 그리기
    const today = new Date();
    //오늘 날짜에 맞는 Date 객체 생성
    if (viewMonth === today.getMonth() && viewYear === today.getFullYear()) {
      //viewMonth와 viewYear가 today와 동일한지 비교
      for (let date of document.querySelectorAll('.this')) {
      //동일한 경우 this 클래스 가진 태그 다 찾아내고
        if (+date.innerText === today.getDate()) {
        //해당 태그의 문자 값을 숫자로 변경해 오늘 날짜오 비교하고
          date.classList.add('today');
          //today 클래스 부여
          break;
          //today는 한개 뿐이라 더이상 탐색 필요 없으니 탈출
        }
      }
    }
.today {
  position: relative;
  color: #FFFFFF;
}

.today::before {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: -1;
  display: block;
  width: 30px;
  height: 30px;
  background-color: #FF0000;
  border-radius: 50%;
  transform: translate(-50%, -50%);
  content: '';
}

today 스타일 부여

화면

0개의 댓글

관련 채용 정보