박스 안에 이미지와 세일기간, 정해놓은 기한에서 1초씩 마이너스되는 기능 구현
세일기간 Date()객체 이용해서 지정
(이건 사실 예제에서 안하는 것 같은데 Date()객체에 set() 구현해보고 싶어서 굳이 안해도 되는거 함...)
그리고 혹시 가능하다면 세일 기한이 끝났을 때 종료되었다는 modal창 나오게 구현해보고 싶다
Date(), setFullYear(), setMonth(), setDate(), setHours(), setMinutes(),
getFullYear(), getMonth(), getDate(), getDay(), getHours(), getMinutes(),
setInterval(), clearInterval(), querySelector, innerText, textContent, Math.floor()
일단 카운트다운은 아직 구현안되었고 Date() set한 부분만 작업했다...
시간 세팅하는 것도 참 오래 걸린다..
일단 그 이미지만 먼저...
일단 어제 만든 navbar에 Sale을 추가했다
완성!!!!!!!!!!!!!!!!!!
마지막에 modal창은 내일 해야겠다...
gif 파일을 속도 조절했더니 버벅거리는지 마우스가 두개네...
<section class="count-clock">
<img class="macbook-img" src="img주소" alt=""/>
<div class="text-box"></div>
</section>
일단 구역을 나누어야 한다
section에 class를 지정해준다
그 안에 할인할 상품 이미지와 text-box를 표시한다
이미지와 text-box를 묶은 이유는 정렬하기 위해서이다
한 줄로 정렬되야 하기 때문이다
(반응형 768px이하에서는 세로로 정렬할 것이다)
text-box는 따로 묶어주고 그 안에 text들은 세로정렬을 해야 한다
<h2>🎊 MacBook Air Last Sale 🎊</h2>
<h4>Giveaway Ends On <span class="end-time"></span></h4>
<p class="lorem-text">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptas saepe est sit, cupiditate quo similique. Odio voluptate, quas minima deleniti quidem inventore numquam voluptatem nam vero eum dignissimos illum unde.
</p>
<div class="time-section"></div>
text-box 안에 들어가는 내용들이다
h4에 빈 span을 넣어주고 여기에 Date() set으로 지정한 날짜를 넣어줄 예정이다
text-box 안에 같이 들어있는 time-section은 카운트다운 시계를 만들어줄 예정이다
따로 묶어준 이유는 위의 이유와 같다
그 안에 text들은 가로정렬을 해야 한다
<div class="time-box">
<p class="time-text days">00</p>
<p>DAYS</p>
</div>
<div class="time-box">
<p class="time-text hours">00</p>
<p>HOURS</p>
</div>
<div class="time-box">
<p class="time-text mins">00</p>
<p>MINS</p>
</div>
<div class="time-box">
<p class="time-text secs">00</p>
<p>SECS</p>
</div>
4구간으로 나눌 것이기 때문에 각각 div로 묶어 주었다
time-text안에 내용들을 남은 시간으로 textContent 해줄 것이다
let saleNow = new Date();
let year = saleNow.setFullYear(2022);
let month = saleNow.setMonth(10); // 0~11로 표시되기 때문에 11월이라 10으로 변경해야한다
let date = saleNow.setDate(30);
let hours = saleNow.setHours(11);
let minutes = saleNow.setMinutes(30);
let month = saleNow.setMonth(10); // 0~11로 표시되기 때문에 11월이라 10으로 변경해야한다
일단.
세일 마지막 날짜 세팅을 해줘야한다
Date() 객체로 set을 사용해서 연도, 월, 일자, 시간, 분, 초, 밀리초를 원하는 것으로 정할 수 있다
처음에 set만 하면 되는 줄 알고 console.log(year)했더니
???뭐하는 짓이야?
2022로 설정하면 나오는 줄 알고 출력했는데 저렇게 출력되었다..
그래서 초단위로 나눠야 하나 해서 2022 / 60 / 60 / 24 / 1000 을 했는데 NaN...
구글링하니 set을 하고 get으로 표시를 해야 한다고 한다...
let getYear = saleNow.getFullYear();
let getMonth = saleNow.getMonth();
let getDate = saleNow.getDate();
let getDay = saleNow.getDay();
let getHours = saleNow.getHours();
let getMinutes = saleNow.getMinutes();
set으로 지정한 날짜를 get으로 각각 변수에 지정해준다
여기서 주의해야할 점은 Month, day는 숫자로 출력되기 때문에 배열을 만들어 준다
let days = ["Sunday", "Monday", "Tuseday", "Wednesday", "Thursday", "Friday", "Saturday"];
let months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
배열에 접근하려면 months[index]로 접근해야 한다
일단 set값이 잘 되었는지 확인하기 위해 console.log로 출력해본다
console.log(
`${days[getDay]}, ${getDate} ${
months[getMonth] // month[getMonth-1]을 했었는데 위에서 이미 10으로 해줬기 때문에 빼지 않는다
} ${getYear} ${getHours}:${getMinutes} AM`
);
// Friday, 30 November 2022 11:30 AM 출력
months[getMonth] // month[getMonth-1]을 했었는데 위에서 이미 10으로 해줬기 때문에 빼지 않는다
백틱으로 감싸주고 days[getDay]를 넣어주고, months[getMonth - 1]을 해준다
months는 index는 0부터 시작하기 때문에 -1을 해주었고 days는 set에서 지정해주는 것이 아니라 자동으로 출력되기 때문에 출력될 때 일요일 = 0으로 출력된다
그래서 굳이 -1을 할 필요가 없다
잘 출력되는 것이 확인 되었으니 js파일에 innerText를 진행해본다
const endTime = document.querySelector(".end-time");
const saleTime = `${days[getDay]}, ${getDate} ${
months[getMonth - 1]
} ${getYear} ${getHours}:${getMinutes} AM`;
endTime.innerText = saleTime;
일단 아까 h4에서 빈 span을 가져온다
그리고 innerText에 출력되는 것을 백틱으로 넣어준다.
Giveaway Ends On 뒤에 붙는 것을 확인할 수 있다
const countDown = function () {
let saleDate = new Date(saleNow); // saleTime이 아니라 saleNow를 넣어야 한다
let calSecond = 1000;
let calMinute = calSecond * 60;
let calHour = calMinute * 60;
let calDay = calHour * 24;
let countTimer;
let saleDate = new Date(saleNow); // saleTime이 아니라 saleNow를 넣어야 한다
saleTime을 출력해보면이렇게 출력되기 때문에 밑에서 현재 시간을 출력한 내역과 다르기 때문에 계산이 되지 않아서 NaN이 출력되는 것이다
countDown 함수를 지정해준다
그 안에 saleDate를 변수로 지정하고 new Date를 지정해준다
그리고 안에 위에서 set으로 받아오고 get으로 지정한 saleTime을 saleNow를 argument로 넣어준다
const saleTime = `${days[getDay]}, ${getDate} ${
months[getMonth - 1]
} ${getYear} ${getHours}:${getMinutes} AM`;
지정한 시간에서 현재 시간을 빼줘야 하기 때문에 saleTime을 new Date()에 넣고 saleDate에 할당해서 위에서 지정한 시간을 설정한다
초, 분, 시간, 일 단위를 변수에 담아서 할당해준다 countTimer도 일단 변수만 지정해준다
해당 변수들을 지정하는 이유는 밑에 다시 설명하겠다
function showTime() {
let now = new Date();
let saleEnd = saleDate - now;
if (saleEnd < 0) {
clearInterval(countTimer);
// modal 구현 예정
}
countDown 함수 안에 showTime 함수를 지정해준다
time-text에 시간 text를 -1초씩 변경되어 보이게 하기 위한 함수이다
함수 안에 now 변수에 새로운 현재 시간 Date()를 지정해준다
saleEnd 변수를 새로 선언하고 위에서 지정한 시간(saleDate)에 현재 시간(now)을 뺀 값을 할당한다
만약 saleEnd가 0보다 작으면 clearInterval(countTimer)를 실행해서 타이머를 종료한다
'이벤트가 종료되었습니다'라는 창을 modal 창으로 구현할 예정이다
이제 각 일, 시간, 분, 초를 지정해줘야 하는데 그전에 일단 saleEnd 값을 확인해봐야 한다
console에 saleEnd를 찍어보면 밀리초로 출력되어 나온다
console.log(saleEnd)
그래서 이제 계산을 해야한다
let days = Math.floor(saleEnd / calDay);
let hours = Math.floor((saleEnd % calDay) / calHour);
let minutes = Math.floor((saleEnd % calHour) / calMinute);
let seconds = Math.floor((saleEnd % calMinute) / calSecond);
그래서 Math.floor로 소수점 뒷자리를 버려주고(내림) 할당한다
위에 calDay, calHour, calMinute, calSecond를 할당한 이유이다
코드가 길어지기 때문에 가독성을 높이기 위해!
그리고 00일 00시간 00분 00초 이렇게 2자리로 설정을 하고 싶다면
이 코드로 days, hours, minutes, seconds를 변경해주면 된다
// let seconds = String(Math.floor((saleEnd % calMinute) / calSecond)).padStart(2, "0");
나는 한자리가 내 눈에 더 예쁜 것 같아서 padStart를 쓰지 않았다
padStart() 에 관한 설명
String 객체 메소드이며 현재 문자열의 시작을 다른 문자열로 채워서 주어진 길이를 만족하는 새로운 문자열을 반환한다. 채워넣기는 대상 문자열의 시작(좌측)부터 적용된다
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
padStart(2, '0') 이렇게 쓰면 2자리를 맞추고 비어있을 경우 0으로 채운다는 뜻이다
이 메서드를 쓸 때 주의해야 할 점은 현재 받아오는 값들은 다 숫자이기 때문에 문자열로 변경해주고 사용해야한다
String(숫자).padStart(2, '0')
이제 text 변경을 해야한다
index.html에서 time-box안에 time-text에 각각 days, hours, mins, secs를 class로 지정해주고 querySelector로 가져온다
const textDays = document.querySelector(".days");
const textHours = document.querySelector(".hours");
const textMins = document.querySelector(".mins");
const textSecs = document.querySelector(".secs");
textDays.textContent = days;
textHours.textContent = hours;
textMins.textContent = minutes;
textSecs.textContent = seconds;
그리고 각각의 값에 맞는 일, 시간, 분, 초를 textContent로 변경해준다
countTimer = setInterval(showTime, 1000);
처음 변수로 지정만 했던 countTimer에 setInterval()을 지정해준다
1초씩 마이너스 될거니까 showTime 함수를 1초마다 출력되도록 1000을 입력한다
주의할 점
: showTime이 함수인데 ()를 쓰지 않는 이유는 addEventListener와 유사한 방식이라서 그런것 같다
()를 쓰게 되면 화면에 아에 한번만 나오고 -1씩 되지 않는다
-1씩 될 때마다 함수를 실행시킬 것이기 때문에 ()를 쓰지 않는다
여기까지만 작성하고 새로고침하면 변경되지 않고 그대로이다
왜냐?
함수 실행을 안해줬으니까
그것도 모르고 하.. 왜 안나오냐 왜 왜 안나오냐 도대체를 외치다 생각해보니 함수 실행을 안해줬다는 생각이 들었다
countDown();
마지막 줄에 함수실행을 하면 구현 작업 이미지처럼 -1초씩 제대로 출력되는 것을 확인할 수 있다
마지막에 지정시간이 종료되었을 때 -1이 화면에 남아있는 것을 수정했다
이부분은 코드 순서가 변경된 것이라 변경된 showTime() 함수 내 코드를 올리는 것이 더 나을 것 같다
function showTime() {
let now = new Date();
let saleEnd = saleDate - now;
let textDays = document.querySelector(".days");
let textHours = document.querySelector(".hours");
let textMins = document.querySelector(".mins");
let textSecs = document.querySelector(".secs");
let days = Math.floor(saleEnd / calDay);
let hours = Math.floor((saleEnd % calDay) / calHour);
let minutes = Math.floor((saleEnd % calHour) / calMinute);
let seconds = Math.floor((saleEnd % calMinute) / calSecond);
if (saleEnd < 0) {
clearInterval(countTimer);
// modal 창 구현
textDays.textContent = 0;
textHours.textContent = 0;
textMins.textContent = 0;
textSecs.textContent = 0;
} else {
textDays.textContent = days;
textHours.textContent = hours;
textMins.textContent = minutes;
textSecs.textContent = seconds;
}
}
querySelector로 가져온 4가지 값을 위쪽으로 올려주고 시간 계산 변수도 위로 올려준다
if문으로 지정된 시간이 종료되었을 때 textContent를 0으로 변경하고 else 경우 각 시간을 넣어준다
확실히 시간 카운트는 너무 헷갈린다
일단 좀 쉬어야겠다
내일 일어나서 modal창 구현해봐야겠다
수정할 부분이 생겼다
오늘 modal 창을 구현해보니 오류가 있었다
1. 받아오는 지정 시간을 잘못받아왔고 그래서 다른 시간대로 변경하니 오류가 생겨서 타이머가 작동하지 않고 NaN이 떴다
어제는 몰랐는데 오늘보니 지정한 시간(11/30)이 수요일인데 금요일로 출력된 것을 확인했다
2. 해당 문제 해결 후 지정한 시간이 종료되었을 때 0이 아니라 -1로 계속 찍혔다