-
[JavaScript] 일반적인 달력 만들기 - 날짜 이동, 날짜 구분, 오늘 표시만학도 프로젝트/JavaScript Calendar 2020. 8. 7. 00:16
지난 포스트 마지막에 정리한 남은 일들을 다시 한번 훑어보면
1. 지난달 다음 달 오늘 날짜로 돌아가는 기능 만들기
2. 지난 달 부분과 다음 달 부분을 조금 투명하게 하기
3. 오늘 날짜 표기하기
총 3가지였습니다.
그럼 1번부터 하나씩 차근차근 해결해보죠.
생각해보면 일단 달력을 그리는 로직은 모두 잘 만들어 뒀으니깐, 지난달, 다음 달 오늘로 Date객체의 정보만 수정해주면 됩니다.
그래서 그동안 만든 코드에서 date부분만 남기고 나머지를 함수로 만들어 줍시다.
// 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();
이렇게 함수로 빼뒀으니 재사용하기가 훨씬 편해졌죠?
그래서 이 함수를 활용해서, 지난 달, 다음 달, 그리고 오늘로 이동하는 세 가지 함수를 아래와 같이 만들어 줄 수 있습니다.
let date = new Date(); // ...( 생략 )... const prevMonth = () => { date.setMonth(date.getMonth() - 1); renderCalendar(); } const nextMonth = () => { date.setMonth(date.getMonth() + 1); renderCalendar(); } const goToday = () => { date = new Date(); renderCalendar(); }
한 가지 주의해야 될 부분은 goToday 함수에서 date 값을 재할당해줘야 해서, 가장 첫 번째 줄에 있는 dete변수를 const가 아니라 let으로 수정해 줘야 합니다 :)
그러고 나서 이 함수를 버튼에 이벤트로 넣어줘야겠죠?
addEventListener를 달아도 되긴 하지만 그냥 간단하게 HTML 태그에 onclick 속성으로 추가해 주겠습니다.
<!-- ... 생략 ... ---> <div class="nav"> <button class="nav-btn go-prev" onclick="prevMonth()"><</button> <button class="nav-btn go-today" onclick="goToday()">Today</button> <button class="nav-btn go-next" onclick="nextMonth()">></button> </div> <!-- ... 생략 ... --->
이제 코드를 실행시키면 nav 버튼에 따라서 클릭했을 때 날짜 이동이 잘 되는 걸 확인할 수 있습니다 :)
그럼 이제 두 번째 문제를 해결해 봅시다.
이전 달과 다음 달 부분의 투명도를 조금 조절해줘서 이번 달 날짜들과의 구분을 조금 지어줘야 하는데요.
스타일을 주기 위해서 date를 그리는 부분에 html 태그를 조금 수정해 주도록 하겠습니다.
// ...( 생략 )... // 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>`; }) // ...( 생략 )...
dates 배열을 모두 만들고서 forEach로 HTML을 만드는 부분인데요.
지난달 부분을 알아내기 위해서 첫날의 index(firstDateIndex),를 찾았고,
다음 달 부분을 알아내기 위해서 마지막 날의 index(lastDateIndex)를 찾아줬습니다.
그러고 나서 삼항 연산자를 통해서 이번 달에 해당하는 부분은 this, 그리고 나머지는 other라는 문자열로 구분해서
날짜 부분을 span 태그로 감싸서 class로 지정해줬는데요.
이렇게 한 이유는, date에 class를 줄 경우에 투명도를 조절하게 되면, 달력의 격자를 그리고 있는 테두리 부분도 같이 투명도가 같이 조절이 되기 때문에 글자만 투명도를 주기 위함입니다 :)
그래서 style.css로 가서 other 부분에 opacity를 .3정도로 돌려주면,
/* ... 생략 ... */ .other { opacity: .3; }
이렇게 지난달과 다음 달 부분은 투명하게 보이면서 이번 달 날짜들과 구분되는 모습을 확인할 수가 있습니다.
이제 진짜 마지막 오늘 날짜 표시만 하면 되는데요!
오늘 날짜는 달력이 그려지고 난 다음에 처리를 해야 되니깐 renderCalendar 마지막 부분에 정리를 해줍시다.
// ... 생략 ... // 오늘 날짜 그리기 const today = new Date(); if (viewMonth === today.getMonth() && viewYear === today.getFullYear()) { for (let date of document.querySelectorAll('.this')) { if (+date.innerText === today.getDate()) { date.classList.add('today'); break; } } } // ... 생략 ...
일단 지금 보이는 날짜가 다른 날짜일 수도 있기 때문에
1. new Date()를 통해 오늘 날짜에 맞는 date객체를 새로 만들어주고,
2. viewMonth와 viewYear가 today의 데이터와 같은지 비교를 한 다음
3. 만약 2번이 충족된다면 this라는 클래스를 가진 태그들을 모두 찾아내서 반복문을 돌려줍니다.
4. 그러고 나서 해당 태그가 가지고 있는 날짜는 문자열이기 때문에 + 단항 연산자를 통해 숫자로 변경한 뒤, 오늘 날짜와 비교하고
5. 4번이 충족된다면 해당 태그에 today라는 클래스를 추가하고 break로 반복문을 종료해 주는 코드라고 볼 수 있습니다.
5번에서 break를 하는 이유는 오늘 날짜는 하나밖에 없기 때문에 찾으면 더 이상 뒤의 반복을 할 필요가 없기 때문입니다 :)
자 그러면 이제 오늘 날짜가 걸린 span 태그에는 today라는 클래스가 추가되었을 텐데요.
style.css로 돌아가서 today에 대한 스타일을 정리해주면 되겠죠?!
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: ''; }
오늘 날짜까지 잘 출력이 되는 모습을 확인할 수가 있습니다.
이렇게 해서 일반적인 달력 만들기는 마무리하고,
다음 포스트는 또 영상으로 찾아뵐게요~ :)
생각보다 복잡하게 만든 것 같긴 한데,
더 좋은 방향이나 조언 있으시면 댓글 꼭 남겨주시면, 성장에 더 힘을 얻도록 하겠습니다!
감사합니다 :)
[2021-9-11 추가내용]위 코드에서 한 가지 버그를 발견했습니다!
궁금하신분은 [JavaScript] 일반적인 달력 만들기 - 날짜 이동 버그 수정하기! 글을 참고해 주세요 :)
오류가 있었던 점 대단히 죄송합니다.
'만학도 프로젝트 > JavaScript Calendar' 카테고리의 다른 글
[JavaScript] 일반적인 달력 만들기 - 날짜 이동 버그 수정하기! (2) 2021.09.11 [JavaScript] 일반적인 달력 만들기 - 영상 (0) 2021.04.16 [JavaScript] 일반적인 달력 만들기 - 스타일 입히기 (0) 2020.08.06 [JavaScript] 일반적인 달력 만들기 - 날짜 가져오기 (9) 2020.08.05 [JavaScript] 일반적인 달력 만들기 - HTML 뼈대 잡기 (0) 2020.08.03