Untitled

제작 기간: 2024.07 ~ 2024.07 기여도: 퍼블리싱 100% 사용 기술: HTML, SCSS, JavasScript(ES6+), GSAP URL: https://kimbangul.github.io/clynder/

GSAP 라이브러리를 활용한 인터랙션 구현에 중점을 두어 클론 코딩한 사이트입니다.

🔍Overview


아날로그 시계 만들기

Untitled

// _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에서 설정해 준 애니메이션에 의해 시침/분침/초침이 움직이게 됩니다.

양쪽으로 텍스트 움직이기

Untitled

.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;
};
ㅌ