제작 기간: 2024.07 ~ 2024.07 기여도: 퍼블리싱 100% 사용 기술: HTML, SCSS, JavasScript(ES6+), GSAP URL: https://kimbangul.github.io/clynder/
GSAP 라이브러리를 활용한 인터랙션 구현에 중점을 두어 클론 코딩한 사이트입니다.
// _animation.scss
@keyframes ani__clock {
0% {
transfrom: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
// _main.scss
&-group {
&-hour,
&-sec,
&-min {
transform-origin: 50%;
transform: rotate(0);
animation-name: ani__clock;
animation-iteration-count: infinite;
}
&-hour { // 시침
animation-duration: 43200s;
animation-timing-function: linear;
}
&-sec { // 초침
animation-duration: 60s;
animation-timing-function: steps(60);
}
&-min { // 분침
animation-duration: 3600s;
animation-timing-function: linear;
}
}
시침, 초침, 분침은 360도씩 회전하므로 0에서 360도까지 회전하는 애니메이션을 만든 후, 요소들마다 animation-duration
을 다르게 설정하여 몇 초에 한바퀴를 도는지 설정해 줍니다. 초침의 경우, steps
속성을 사용하여 1초에 한 단계씩 애니메이션을 보여주도록 설정했습니다.
// PARAM time diff
const timeDiff = {
kr: 9 * 60 * 60 * 1000,
london: 1 * 60 * 60 * 1000,
losAngeles: -7 * 60 * 60 * 1000,
santiago: -4 * 60 * 60 * 1000,
newYork: -4 * 60 * 60 * 1000,
dallas: -5 * 60 * 60 * 1000,
bucharest: 3 * 60 * 60 * 1000,
durham: 1 * 60 * 60 * 1000,
};
// FUNCTION utc시간과의 차이를 매개변수로 입력받아 시간을 구하는 함수
const getTimeFromUtc = (diff) => {
// diff: number(utc 시간과 구하고자 하는 시간과의 차이)
const currDate = new Date();
const utcTime = currDate.getTime() + currDate.getTimezoneOffset() * 60 * 1000;
return new Date(utcTime + diff);
};
// FUNCTION DateTime을 시/분/초 단위로 나누기
const getTime = (time) => {
return {
hour: padToDigit(time.getHours()),
min: padToDigit(time.getMinutes()),
second: padToDigit(time.getSeconds()),
};
};
각 도시의 현재 시간을 구할 경우, 단순히 new Date()
를 이용하여 구하면 로컬 클라이언트 pc의 시간에 따라 잘못된 값을 보여줄 수 있기 때문에 UTC시간을 구하고, UTC시간과 각 도시 시간과의 차를 이용하여 시간을 구하는 과정을 거쳤습니다.
// FUNCTION 시계 style(각도) 설정
const setClockHands = (time, selector) => {
// time = "HH:mm:ss" 형식의 문자열
const { hour, min, second } = getTime(time);
const clock = document.querySelector(selector);
// 시침의 각도 설정 (시간에 따라 360/12 = 30도씩 회전 + 분에 따른 보정)
const hourAngle = (hour % 12) * 30 + min * 0.5;
clock.querySelector(
'.clock-group-hour'
).style.transform = `rotate(${hourAngle}deg)`;
// 분침의 각도 설정 (분에 따라 360/60 = 6도씩 회전 + 초에 따른 보정)
const minuteAngle = min * 6 + second * 0.1;
clock.querySelector(
'.clock-group-min'
).style.transform = `rotate(${minuteAngle}deg)`;
// 초침의 각도 설정 (초에 따라 360/60 = 6도씩 회전)
const secondAngle = second * 6;
clock.querySelector(
'.clock-group-sec'
).style.transform = `rotate(${secondAngle}deg)`;
};
// PARAM Datetime 객체들
const dateTimeList = {
kr: () => getTimeFromUtc(timeDiff.kr),
london: () => getTimeFromUtc(timeDiff.london),
losAngeles: () => getTimeFromUtc(timeDiff.losAngeles),
santiago: () => getTimeFromUtc(timeDiff.santiago),
newYork: () => getTimeFromUtc(timeDiff.newYork),
dallas: () => getTimeFromUtc(timeDiff.dallas),
bucharest: () => getTimeFromUtc(timeDiff.bucharest),
durham: () => getTimeFromUtc(timeDiff.durham),
};
// FUNCTION 세계시각 설정
const setWorldClock = () => {
const clockList = document.querySelectorAll("[data-area='2'] .clock");
clockList.forEach((el) => {
const cityName = el.getAttribute('data-clock');
// dom에 설정되어 있는 data-clock 속성에 의해 시각이 설정됨.
setClockHands(dateTimeList[cityName](), `[data-clock='${cityName}']`);
});
};
getTimeFromUtc()
와 getTime()
을 통해 구한 시간을 바탕으로 아날로그 시계의 시침/분침/초침의 초기 위치를 설정해 주었습니다. 초기 설정을 한 후에는 _animation.scss에서 설정해 준 애니메이션에 의해 시침/분침/초침이 움직이게 됩니다.
.time {
position: relative;
&__text {
&-box {
width: 100%;
overflow: hidden;
}
position: relative;
left: 50%;
z-index: 1;
font-family: $font__Rhymes;
font-size: 23rem;
font-weight: 100;
text-transform: uppercase;
white-space: nowrap;
$x: ('-70rem', '-34rem', '-97rem', '-25rem', '-7rem', '-98rem', '-100rem');
@for $i from 1 to 8 {
&:nth-child(#{$i}) {
margin-left: #{nth($x, $i)};
}
}
// FUNCTION 양쪽으로 움직이는 텍스트
const setMoveHorizontalText = (array) => {
// array: selector list
const tl = gsap.timeline({});
array.forEach((el, idx) => {
tl.to(
el,
{
x: () => (idx % 2 === 0 ? '-10rem' : '10rem'),
repeatRefresh: true,
},
`text+=${idx * 0.05}`
);
});
return tl;
};
ㅌ