[JS30] JavaScript30 Day 2
서론
JavaScript30 Day 2, 오늘은 JS로 시계를 만드는 미션이다.
시:분:초 이런 형식이 아니라 시침, 분침, 초침이 돌아가는 시계를 만드는 것이다.
혼자서 해보려고 했으나 오늘도 실패… 풀이를 보지 않고 미션을 풀 수 있는 날이 오길 바란다. 그럼 이제 시작하자!
구현
링크
Task
- 시곗바늘 정각을 가리키게 만들기
- 시곗바늘 회전시키기
- 시간에 맞춰 매초 시곗바늘 회전시키기
1. 시곗바늘 정각을 가리키게 만들기
우선 시곗바늘들이 12시를 가리키고 있는 것이 아니라, 9시 방향을 가리키고 있어서 transform: rotate(90deg);
를 한다.
2. 시간에 따라 시곗바늘 회전시키기
const now = new Date();
const seconds = now.getSeconds();
const secondsDegrees = ((seconds / 60) * 360) + 90;
const mins = now.getMinutes();
const minsDegrees = ((mins / 60) * 360) + ((seconds / 60) * 6) + 90;
const hours = now.getHours();
const hoursDegrees = ((hours / 12) * 360) + ((mins / 60) * 30) + 90;
new Date()
를 사용하면 요일 달 날짜 HH:MM:SS GMT+0900 (Korean Standard Time)
형식으로 시간을 알 수 있다. get~
함수들로 시, 분, 초를 각각 상수에 저장한다.
이제 시곗바늘을 시간에 맞게 회전시켜야 하는데 몇 도씩 회전시켜야 할까?
시침은 60초마다 시계 한 바퀴를 돈다. 그럼 360/60 = 6, 즉 1초에 6도씩 회전시키면 된다.
분침 또한 60분 동안 한 바퀴를 돈다. 그럼 1분에 6도씩 회전시키면 되는데, 시계를 자세히 보면 분침이 1분에 한 번 움직이는 것이 아니라, 초침이 돌아감과 함께 조금씩 움직이고 있다.
그럼 1분에 6도씩 움직이니까 6/60 = 0.1도 해서 매초 0.1도씩 움직이면 되는 것이다.
시침도 마찬가지로 360/12 = 30, 30/60 = 0.5, 즉 매분 0.5도씩 회전시키면 된다. (+90을 하는 이유는 맨 처음 시곗바늘이 정각을 가리키고 있지 않아서 그렇다.)
secondHand.style.transform = `rotate(${secondsDegrees}deg)`;
minHand.style.transform = `rotate(${minsDegrees}deg)`;
hourHand.style.transform = `rotate(${hoursDegrees}deg)`;
각도를 구했으니 이제 시곗바늘을 움직이도록 하자. 회전은 위에서 말했듯 transform: rotate()
를 사용하면 된다.
그러나 여기서 문제가 있는데, 바로 저렇게 사용하면 div의 한가운데를 중심으로 회전하는 것이다. 내가 원하는 방식은 div의 오른쪽 가운데를 중심으로 회전하는 것이다. 그래서 css에 transform-origin 속성을 추가했다.
회전축 문제도 해결했으니 이제 매초 회전시키면 된다.
3. 시간에 맞춰 매초마다 시곗바늘 회전시키기
1초에 한 번씩 시곗바늘이 회전해야 한다. 이럴 때 사용하는 것이 바로 setInterval이다. 1초는 1000임으로 매초 2번을 실행시키면 되는 것이다.
그런데 완성본을 보면 시곗바늘이 움직일 때마다 반동이 있다. 바로 transition-timing-function의 cubic-bezier()
를 사용한 것이다.
cubic-bezier
란 3차원 베지어 곡선을 의미하는 것인데 부드러운 곡선을 모델링하기 위해 컴퓨터 그래픽에 널리 사용되는 곡선 모델이라고 한다. 더 자세한 설명은 생략한다.
여튼 이 transition
을 0.05초씩, transition-timing-function
속성으로 전환의 효과를 제어하면 반동을 구현할 수 있다.
F12를 눌러 개발자 모드에서 element.style로 효과를 조절해도 되고, 아니면 cubic-bezier 이 웹사이트를 사용해도 된다.
TLD
오늘도 역시 새로운 것투성이였다. JS에서 사용한 것은 다 아는 것들인데 오히려 CSS의 처음 보는 다양한 transition(Coding Factory) transition(MDN) 효과들이 많았다. transform: rotate(90deg);
와transition: all 0.05s;
빼고 다 처음 보는 것들이다.
CSS로 반동을 구현할 수 있다니!!! 역시 웹의 세계는 무궁무진하고 내가 모르는 신기한 JS API들 투성이다. 그래도 기초적인 것들은 어느 정도 섭렵했다고 생각했는데 아직도 배울 것이 이렇게 많다니…! 신난다 더 열심히 공부해야지!!! 웹 마스터가 되는 그날까지 파이퉹!!!!
최종 코드
JS:
const secondHand = document.querySelector(`.second-hand`);
const minHand = document.querySelector(`.min-hand`);
const hourHand = document.querySelector(`.hour-hand`);
function setClock() {
const now = new Date();
const seconds = now.getSeconds();
const secondsDegrees = ((seconds / 60) * 360) + 90;
const mins = now.getMinutes();
const minsDegrees = ((mins / 60) * 360) + ((seconds / 60) * 6) + 90;
const hours = now.getHours();
const hoursDegrees = ((hours / 12) * 360) + ((mins / 60) * 30) + 90;
secondHand.style.transform = `rotate(${secondsDegrees}deg)`;
minHand.style.transform = `rotate(${minsDegrees}deg)`;
hourHand.style.transform = `rotate(${hoursDegrees}deg)`;
}
setInterval(setClock, 1000);
setClock();
CSS:
.hand {
width: 50%;
height: 6px;
background: black;
border-radius: .3rem; /* 시곗바늘 모서리를 둥글게 만들었다 */
position: absolute;
top: 50%;
transform: rotate(90deg);
transition: all 0.05s;
transform-origin: 100%;
transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
}
/* 시침을 짧게 만들었다 */
.hour-hand {
width: 35%;
left: 15%;
}
/* 초침을 얇게 */
.second-hand {
height: 3px;
}
댓글남기기