CSS + JS Clock

위풍당당수·2023년 11월 26일
0

Javascript30

목록 보기
2/10

소스코드

HTML

<body>
    <div class="clock">
      <div class="clock-face">
        <div class="hand hour-hand"></div>
        <div class="hand min-hand"></div>
        <div class="hand second-hand"></div>
      </div>
    </div>
</body>

CSS

html {
  background: #018ded url(https://unsplash.it/1500/1000?image=881&blur=5);
  background-size: cover;
  font-family: "helvetica neue";
  text-align: center;
  font-size: 10px;
}

body {
  margin: 0;
  font-size: 2rem;
  display: flex;
  flex: 1;
  min-height: 100vh;
  align-items: center;
}

.clock {
  width: 30rem;
  height: 30rem;
  border: 20px solid white;
  border-radius: 50%;
  margin: 50px auto;
  position: relative;
  padding: 2rem;
  box-shadow: 0 0 0 4px rgba(0, 0, 0, 0.1), inset 0 0 0 3px #efefef,
    inset 0 0 10px black, 0 0 10px rgba(0, 0, 0, 0.2);
}

.clock-face {
  position: relative;
  width: 100%;
  height: 100%;
  transform: translateY(-3px); /* account for the height of the clock hands */
}

.hand {
  width: 50%;
  height: 6px;
  background: black;
  position: absolute;
  top: 50%;
  transform-origin: 100%;
  transform: rotate(90deg);
  transition: all 0.03s;
  transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
}

JS

const secondHand = document.querySelector(".second-hand");
const minHand = document.querySelector(".min-hand");
const hourHand = document.querySelector(".hour-hand");

function setDate() {
const now = new Date();
const seconds = now.getSeconds();
const minutes = now.getMinutes();
const hours = now.getHours();
const secondsDegrees = (seconds / 60) * 360 + 90;
const minutesDegrees = ((minutes / 60) * 360) + ((seconds / 60) * 6) + 90;
const hoursDegrees = ((hours / 12) * 360) + ((minutes / 60) * 30) + 90;

secondHand.style.transform = `rotate(${secondsDegrees}deg)`;
minHand.style.transform = `rotate(${minutesDegrees}deg)`;
hourHand.style.transform = `rotate(${hoursDegrees}deg)`;
}

setInterval(setDate, 1000);
setDate();

결과

TIL

transform-origin

css 프로퍼티인 transform-origin는 엘리먼트를 transform할 기준점을 설정하는 프로퍼티이다.
이번 챌린지에서는 transform-origin=100%로 작성하여 x-offset의 가장 오른쪽을 기준점으로 설정했다.

/* One-value syntax */
transform-origin: 2px;
transform-origin: bottom;

/* x-offset | y-offset */
transform-origin: 3cm 2px;

/* x-offset-keyword | y-offset */
transform-origin: left 2px;

/* x-offset-keyword | y-offset-keyword */
transform-origin: right top;

/* y-offset-keyword | x-offset-keyword */
transform-origin: top right;

/* x-offset | y-offset | z-offset */
transform-origin: 2px 30% 10px;

/* x-offset-keyword | y-offset | z-offset */
transform-origin: left 5px -3px;

/* x-offset-keyword | y-offset-keyword | z-offset */
transform-origin: right bottom 2cm;

/* y-offset-keyword | x-offset-keyword | z-offset */
transform-origin: bottom right 2cm;

/* Global values */
transform-origin: inherit;
transform-origin: initial;
transform-origin: revert;
transform-origin: revert-layer;
transform-origin: unset;

0초가 되었을 때 transition 글리치 해결하기

구현은 했지만 0초가 되면 transition으로 인해 초침이 원점으로 돌아가는 글리치 현상이 발생한다.
글리치 현상

이는 변수 secondsDegrees의 값이 마지막값 444에서 초기값 90이 되는 과정에서 transition이 적용되기 때문에 발생하는 현상이다. 이 문제는 transition을 제거하면 해결되는 것이었지만, 강의에서 제안한 if/else 문으로 해결해보았다.

function setDate() {
  const secondHand = document.querySelector(".second-hand");
  const minHand = document.querySelector(".min-hand");
  const hourHand = document.querySelector(".hour-hand");

  const now = new Date();
  const seconds = now.getSeconds();
  const minutes = now.getMinutes();
  const hours = now.getHours();
  const secondsDegrees = (seconds / 60) * 360 + 90;
  const minutesDegrees = (minutes / 60) * 360 + (seconds / 60) * 6 + 90;
  const hoursDegrees = (hours / 12) * 360 + (minutes / 60) * 30 + 90;

  if (secondsDegrees === 90) {
    secondHand.style.transition = "none";
  } else {
    secondHand.style.transition = "";
  }
  
  secondHand.style.transform = `rotate(${secondsDegrees}deg)`;
  minHand.style.transform = `rotate(${minutesDegrees}deg)`;
  hourHand.style.transform = `rotate(${hoursDegrees}deg)`;
}

setInterval(setDate, 1000);
setDate();

변수 secondsDegrees의 값이 90일 때는 transition을 none을 통해 제거하고 그외에는 transtion을 리셋하도록 빈 문자열을 할당했다.

secondHand.style.transition = ""; 이런 식으로 빈 문자열 값을 할당하면 기존의 인라인 스타일을 제거함으로써 해당 엘리먼트의 인라인 스타일은 리셋시킨다. 그리고 기존의 스타일시트에 있는 transition 속성을 적용한다.

글리치 해결

profile
가장 어려워 하는 '기록'하기

0개의 댓글