[JavaScript30] 2. Clock | setInterval(), transform, transition
language/javascript

[JavaScript30] 2. Clock | setInterval(), transform, transition

πŸ“ƒ μš”ꡬ사항

  1. ν˜„μž¬ μ‹œκ°„μ— 맞게 μ‹œκ³„λ₯Ό λ™μž‘μ‹œν‚¨λ‹€.
  2. 이 λ•Œ, λ°”λŠ˜μ˜ ν•œ μͺ½ 끝은 κ°€μš΄λ°μ— κ³ μ •λ˜μ–΄ μ‹œκ³„ λ°©ν–₯으둜 움직여야 ν•œλ‹€.

 

✨ κ²°κ³Όν™”λ©΄

 

πŸ’» μ†ŒμŠ€μ½”λ“œ

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>JS + CSS Clock</title>
  </head>
  <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>

    <style>
      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-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);
      }

      .hour-hand {
        background: #ff8080;
      }

      .min-hand {
        background: #ffff80;
      }

      .second-hand {
        background: #d9d9d9;
      }
    </style>

    <script>
      const hourHand = document.querySelector(".hour-hand");
      const minuteHand = document.querySelector(".min-hand");
      const secondHand = document.querySelector(".second-hand");

      function setDate() {
        const now = new Date();
        let hours = now.getHours();
        const minutes = now.getMinutes();
        const seconds = now.getSeconds();

        const hoursDegrees = (hours / 12) * 360 + 90;
        const minutesDegrees = (minutes / 60) * 360 + 90;
        const secondsDegrees = (seconds / 60) * 360 + 90;

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

        console.log(hours);
      }

      setInterval(setDate, 1000);
    </script>
  </body>
</html>

 

πŸ“– TIL

setInterval()

setInterval()은 μΌμ •ν•œ μ‹œκ°„ κ°„κ²©μœΌλ‘œ νŠΉμ • μ½”λ“œλΈ”λ‘μ„ 반볡적으둜 μ‹€ν–‰ν•˜λŠ” ν•¨μˆ˜μ΄λ‹€.

setInterval(() => {
	console.log('Hello');
}, 3000);

μœ„μ™€ 같이 μž‘μ„±ν•˜λ©΄, 3μ΄ˆμ— ν•œ λ²ˆμ”© Helloκ°€ μ½˜μ†”μ— 찍히게 λœλ‹€. 참고둜 μ§€μ •ν•˜λŠ” ν•¨μˆ˜λŠ” κΌ­ 읡λͺ…일 ν•„μš”λŠ” μ—†κ³ , ν•¨μˆ˜μ— 이름을 λΆ€μ—¬ν•˜κ±°λ‚˜ λ‹€λ₯Έ κ³³μ—μ„œ ν•¨μˆ˜λ₯Ό μ •μ˜ν•˜κ³  μ°Έμ‘°(reference)λ₯Ό 전달할 μˆ˜λ„ μžˆλ‹€. 또, ν•„μš”ν•œ λ§€κ°œλ³€μˆ˜λ₯Ό 전달할 μˆ˜λ„ μžˆλ‹€.

function print(string) {
	console.log(`Hello ${string}!`);
}

setInterval(print, 1000, "World");

λ§Œμ•½ μ§€μ •λœ μ‹œκ°„μ΄ κ²½κ³Όλ˜μ—ˆμ„ λ•Œ νŠΉμ • μ½”λ“œλΈ”λ‘μ„ ν•œ 번만 μ‹€ν–‰ν•˜κ³  μ‹Άλ‹€λ©΄ setTimeout()을 μ‚¬μš©ν•˜λ©΄ λœλ‹€. setTimeout()의 μ‚¬μš©λ²•μ€ setInterval()κ³Ό λ™μΌν•˜λ‹€.

 

transform

CSS의 속성 쀑 ν•˜λ‚˜λ‘œ, μš”μ†Œμ— νšŒμ „, 크기 쑰절, 기울이기, 이동 효과 등을 λΆ€μ—¬ν•  수 μžˆλ‹€. transform은 μš”μ†Œμ˜ λ³€ν˜•μ„ μΌμœΌν‚¬ 뿐 μ›€μ§μ΄λŠ” 동적인 효과λ₯Ό 쀄 수 μ—†λ‹€. transform 속성을 μ‚¬μš©ν•΄μ„œ 효과λ₯Ό μ£Όκ³ , transition 속성을 μ‚¬μš©ν•΄μ„œ 동적인 효과λ₯Ό μ œμ–΄ν•œλ‹€.

1️⃣ transform

transform function μ„€λͺ… λ‹¨μœ„
translate(x, y) μš”μ†Œμ˜ μœ„μΉ˜λ₯Ό XμΆ•μœΌλ‘œ x만큼, YμΆ•μœΌλ‘œ y만큼 μ΄λ™μ‹œν‚¨λ‹€.
translateX(n), translateY(n)을 톡해 XμΆ• λ˜λŠ” YμΆ•μœΌλ‘œλ§Œ μ΄λ™μ‹œν‚¬ 수 μžˆλ‹€.
px, %, em λ“±
scale(x, y) μš”μ†Œμ˜ 크기λ₯Ό XμΆ•μœΌλ‘œ xλ°°, YμΆ•μœΌλ‘œ yλ°° ν™•λŒ€ λ˜λŠ” μΆ•μ†Œμ‹œν‚¨λ‹€.
scaleX(n), scaleY(n)을 톡해 XμΆ• λ˜λŠ” YμΆ•μœΌλ‘œλ§Œ ν™•λŒ€ λ˜λŠ” μΆ•μ†Œμ‹œν‚¬ 수 μžˆλ‹€.
0κ³Ό μ–‘μˆ˜
skew(x-angle, y-angle) μš”μ†Œλ₯Ό XμΆ•μœΌλ‘œ x κ°λ„λ§ŒνΌ, YμΆ•μœΌλ‘œ y κ°λ„λ§ŒνΌ κΈ°μšΈμΈλ‹€(λΉ„νŠΌλ‹€).
skewX(n), skewY(n)을 톡해 XμΆ• λ˜λŠ” YμΆ•μœΌλ‘œλ§Œ 기울일(λΉ„ν‹€) 수 μžˆλ‹€.
+/- 각도(deg)
rotate(angle) μš”μ†Œλ₯Ό angle만큼 νšŒμ „μ‹œν‚¨λ‹€. +/- 각도(deg)

 

2️⃣ transform-origin

transform-origin 속성은 transform 속성과 ν•¨κ»˜ μ‚¬μš©λ˜λŠ” μ†μ„±μœΌλ‘œ, νšŒμ „ 쀑심(원점, 기쀀점)을 μ§€μ •ν•œλ‹€. transform-origin을 μ‚¬μš©ν•˜λ©΄ rotate(), skew() λ“±μ˜ νšŒμ „, λ³€ν˜• 속성을 μ‚¬μš©ν•˜κΈ° 전에 기쀀점을 μ§€μ •ν•  수 μžˆλ‹€. 초기 값은 50% 50%으둜 ν•΄λ‹Ή μš”μ†Œμ˜ 쀑심점이 λœλ‹€. transform-origin의 속성 값은 λ°±λΆ„μœ¨(%)κ³Ό ν‚€μ›Œλ“œ 쀑 ν•˜λ‚˜λ‘œ μ§€μ •ν•  수 μžˆλ‹€.

λ°±λΆ„μœ¨(%) λŒ€μš© κ°€λŠ₯ν•œ ν‚€μ›Œλ“œ
0% left
0% top
50% center
100% right
100% bottom

μœ„μ˜ ν‘œμ— 따라, transform-origin: 0% 0%, transform-origin: 100% 50% λ“±μœΌλ‘œ λ‚˜νƒ€λ‚Ό 수 μžˆλ‹€. Clock μ†ŒμŠ€μ½”λ“œμ—μ„œλŠ”, λ°”λŠ˜μ˜ ν•œμͺ½ 끝을 bottom right에 λ§žμΆ”κΈ° μœ„ν•΄ λ‹€μŒκ³Ό 같이 μž‘μ„±ν•˜μ˜€λ‹€.

transform-origin: 100%;

 

transition

transition은 CSS 속성을 λ³€κ²½ν•  λ•Œ μ• λ‹ˆλ©”μ΄μ…˜ 속도λ₯Ό μ‘°μ ˆν•˜μ—¬ μ• λ‹ˆλ©”μ΄μ…˜ νš¨κ³Όκ°€ 일정 μ‹œκ°„μ— 걸쳐 λ‹€μ–‘ν•œ λ°©λ²•μœΌλ‘œ μ§„ν–‰λ˜κ²Œλ” ν•œλ‹€.

ν”„λ‘œνΌν‹° μ„€λͺ… κΈ°λ³Έκ°’
transition-property λŒ€μƒμ΄ λ˜λŠ” CSS ν”„λ‘œνΌν‹°λ₯Ό μ§€μ •ν•œλ‹€.
μ§€μ •ν•˜μ§€ μ•ŠλŠ” κ²½μš°μ—λŠ” λͺ¨λ“  ν”„λ‘œνΌν‹°κ°€ νŠΈλžœμ§€μ…˜μ˜ λŒ€μƒμ΄ λœλ‹€.
볡수의 ν”„λ‘œνΌν‹°λ₯Ό μ§€μ •ν•˜λŠ” 경우 μ‰Όν‘œ(,)둜 κ΅¬λΆ„ν•œλ‹€.
단, λͺ¨λ“  CSS ν”„λ‘œνΌν‹°κ°€ νŠΈλžœμ§€μ…˜μ˜ λŒ€μƒμ΄ 될 수 μ—†λ‹€. (ex. display)
all
transition-duration μ§€μ†μ‹œκ°„μ„ 초 λ‹¨μœ„(s) λ˜λŠ” 밀리 초 λ‹¨μœ„(ms)둜 μ§€μ •ν•œλ‹€.
transition-duration ν”„λ‘œνΌν‹°κ°’μ€ transition-property ν”„λ‘œνΌν‹°κ°’κ³Ό 1:1 λŒ€μ‘ν•œλ‹€.
0s
transition-timing-function 효과λ₯Ό μœ„ν•œ 수치 ν•¨μˆ˜λ₯Ό μ§€μ •ν•œλ‹€.
큐빅 베이지어(cubic-bezier)λ₯Ό μ •μ˜ν•˜λŠ” λ„€ 점에 μ˜ν•΄ μ •μ˜λœλ‹€.
미리 μ •ν•΄λ‘” 5개의 ν‚€μ›Œλ“œκ°€ μ œκ³΅λœλ‹€.

β—Ύ ease: 천천히 μ‹œμž‘ν•΄μ„œ, λΉ λ₯΄κ²Œ μ§„ν–‰λ˜κ³ , 천천히 λλ‚œλ‹€.
β—Ύ linear: 처음과 끝이 같은 μ†λ„λ‘œ μ§„ν–‰λœλ‹€.
β—Ύ ease-in: 천천히 μ‹œμž‘ν•œλ‹€.
β—Ύ ease-out: 천천히 λλ‚œλ‹€.
β—Ύ ease-in-out: 천천히 μ‹œμž‘ν•΄μ„œ 천천히 λλ‚œλ‹€.
ease
transition-delay λ³€ν™”ν•œ μ‹œμ κ³Ό μ‹€μ œλ‘œ μ‹œμž‘ν•˜λŠ” 사이에 λŒ€κΈ°ν•˜λŠ” μ‹œκ°„μ„ 초 λ‹¨μœ„(s) λ˜λŠ” 밀리 초 λ‹¨μœ„(ms)둜 μ§€μ •ν•œλ‹€.
즉, ν”„λ‘œνΌν‹°μ˜ 값이 변화해도 일정 μ‹œκ°„ λŒ€κΈ°ν•œ ν›„ νŠΈλžœμ§€μ…˜μ΄ μ‹€ν–‰λ˜λ„λ‘ ν•œλ‹€.
0s
transition λͺ¨λ“  νŠΈλžœμ§€μ…˜ ν”„λ‘œνΌν‹°λ₯Ό ν•œλ²ˆμ— μ§€μ •ν•œλ‹€.
transition: property duration function delay
 
.div1 {
	transition: width 1s ease-in 1s;
}

.div2 {
	transition-property: width, opacity;
    transition-duration: 2s, 1s;
} /* widthλŠ” 2초, opacityλŠ” 4초의 duration을 κ°–λŠ”λ‹€. */

.div2 {
	transition: width 2s, opacity 4s;
} /* transition ν”„λ‘œνΌν‹°λ‘œ μΆ•μ•½ ν‘œν˜„μ΄ κ°€λŠ₯ν•˜λ‹€. */

.div3 {
	transition-property: width, opacity, left, top;
    transition-duration: 2s, 1s;
} /* widthλŠ” 2초, opacityλŠ” 1초, leftλŠ” 2초, top은 1초의 duration */

Clock μ†ŒμŠ€μ½”λ“œμ—μ„œλŠ”, transition-timing-function을 cubic-bezierλ₯Ό μ΄μš©ν•΄μ„œ μ‹œκ³„ λ°”λŠ˜μ— μ• λ‹ˆλ©”μ΄μ…˜μ„ μ£Όμ—ˆλ‹€.

transition-timing-function: cubic-bezier(0.1, 2.7, 0.58, 1);

 

 

 

πŸ‘€ μ°Έκ³ 

youtube Wes Bos

https://www.youtube.com/watch?v=xu87YWbr4X0&list=PLu8EoSxDXHP6CGK4YVJhL_VWetA865GOH&index=2 

 

https://poiemaweb.com/css3-transform

 

https://www.tabmode.com/homepage/transform-origin.html

 

https://poiemaweb.com/css3-transition