새로운 CSS sin() 및 cos() 삼각 함수로 시계 만들기

새로운 CSS sin() 및 cos() 삼각 함수로 시계 만들기

소스 노드 : 1999799

CSS 삼각법 함수가 여기 있습니다! 글쎄요, 최신 버전의 Firefox 및 Safari를 사용하는 경우입니다. CSS에서 이런 종류의 수학적 힘을 갖는 것은 많은 가능성을 열어줍니다. 이 자습서에서는 몇 가지 새로운 기능에 대한 느낌을 얻기 위해 발가락을 물에 담그기로 했습니다. sin()cos().

파이프라인에는 다음과 같은 다른 삼각법 함수가 있습니다. tan() — 그래서 왜 집중 sin()cos()? 원의 가장자리를 따라 텍스트를 배치하는 아이디어에 완벽하게 맞습니다. CSS-Tricks에서 여기에서 다루었습니다. Chris는 Sass 믹스인을 사용하는 접근 방식을 공유했습니다.. 그것은 XNUMX년 전이었으므로 최첨단 치료를 제공합시다.

여기 제가 생각하고 있는 것이 있습니다. 다시 말하지만 현재로서는 Firefox 및 Safari에서만 지원됩니다.

따라서 단어가 원형을 형성하는 것과 정확히 같지는 않지만 원을 따라 텍스트 문자를 배치하여 시계 문자판을 형성합니다. 시작하는 데 사용할 수 있는 마크업은 다음과 같습니다.

<div class="clock"> <div class="clock-face"> <time datetime="12:00">12</time> <time datetime="1:00">1</time> <time datetime="2:00">2</time> <time datetime="3:00">3</time> <time datetime="4:00">4</time> <time datetime="5:00">5</time> <time datetime="6:00">6</time> <time datetime="7:00">7</time> <time datetime="8:00">8</time> <time datetime="9:00">9</time> <time datetime="10:00">10</time> <time datetime="11:00">11</time> </div>
</div>

다음으로 다음은 .clock-face 컨테이너. 나는 사용하기로 결정했다 <time> 태그가있는 datetime 속성을 사용하지 않는 것입니다. 

.clock { --_ow: clamp(5rem, 60vw, 40rem); --_w: 88cqi; aspect-ratio: 1; background-color: tomato; border-radius: 50%; container-type: inline; display: grid; height: var(--_ow); place-content: center; position: relative; width var(--_ow);
}

나는 거기에 약간의 장식을 했지만 우리가 무엇을 하고 있는지 볼 수 있도록 기본 모양과 배경색을 얻기 위해서만 했습니다. 우리가 어떻게 저장하는지 주목하십시오 widthCSS 변수. 나중에 사용하겠습니다. 지금까지 볼 것이 많지 않습니다.

왼쪽에 숫자 1-12의 세로 목록이 있는 큰 토마토 색 원.

일종의 현대 미술 실험처럼 보이죠? 새로운 변수를 도입하자. --_r, 원을 저장하려면 반지름, 이는 원 너비의 절반과 같습니다. 이렇게하면 너비 (--_w) 변경, 반지름 값(--_r)도 업데이트됩니다 — 다른 CSS 수학 함수 덕분에 calc():

.clock { --_w: 300px; --_r: calc(var(--_w) / 2); /* rest of styles */
}

이제 약간의 수학입니다. 원은 360도입니다. 시계에 12개의 레이블이 있으므로 30도마다 숫자를 배치하고 싶습니다(360 / 12). 수학 나라에서 원은 3시에 시작하므로 정오가 실제로 영하 90도 270도(360 - 90).

다른 변수를 추가해 보겠습니다. --_d, 우리는 정도 시계판의 각 숫자에 대한 값입니다. 값을 30도 증가시켜 원을 완성합니다.

.clock time:nth-child(1) { --_d: 270deg; }
.clock time:nth-child(2) { --_d: 300deg; }
.clock time:nth-child(3) { --_d: 330deg; }
.clock time:nth-child(4) { --_d: 0deg; }
.clock time:nth-child(5) { --_d: 30deg; }
.clock time:nth-child(6) { --_d: 60deg; }
.clock time:nth-child(7) { --_d: 90deg; }
.clock time:nth-child(8) { --_d: 120deg; }
.clock time:nth-child(9) { --_d: 150deg; }
.clock time:nth-child(10) { --_d: 180deg; }
.clock time:nth-child(11) { --_d: 210deg; }
.clock time:nth-child(12) { --_d: 240deg; }

자, 이제 손을 더럽힐 시간입니다. sin()cos() 기능! 우리가 하고 싶은 것은 그것들을 사용하여 각 숫자에 대한 X 및 Y 좌표를 가져와 시계 문자판 주위에 적절하게 배치할 수 있도록 하는 것입니다.

X 좌표의 공식은 다음과 같습니다. radius + (radius * cos(degree)). 그것을 우리의 새로운 것에 연결합시다 --_x 변하기 쉬운:

--_x: calc(var(--_r) + (var(--_r) * cos(var(--_d))));

Y 좌표의 공식은 다음과 같습니다. radius + (radius * sin(degree)). 이를 계산하는 데 필요한 것이 있습니다.

--_y: calc(var(--_r) + (var(--_r) * sin(var(--_d))));

숫자를 설정하기 위해 해야 할 몇 가지 정리 작업이 있으므로 숫자에 몇 가지 기본 스타일을 지정하여 절대적으로 배치되고 좌표와 함께 배치되도록 합시다.

.clock-face time { --_x: calc(var(--_r) + (var(--_r) * cos(var(--_d)))); --_y: calc(var(--_r) + (var(--_r) * sin(var(--_d)))); --_sz: 12cqi; display: grid; height: var(--_sz); left: var(--_x); place-content: center; position: absolute; top: var(--_y); width: var(--_sz);
}

주의 --_sz, 우리는 widthheight 순간의 숫자. 지금까지 우리가 무엇을 가지고 있는지 봅시다.

가장자리를 따라 중심에서 벗어난 시간 번호 레이블이 있는 큰 토마토 색 원입니다.

이것은 확실히 시계처럼 보입니다! 각 숫자의 왼쪽 상단 모서리가 원 주변의 올바른 위치에 어떻게 배치되어 있는지 확인하십시오. 각 숫자의 위치를 ​​계산할 때 반경을 "축소"해야 합니다. 우리는 할 수 있습니다 빼다 숫자의 크기(--_sz) 원의 크기(--_w), 반지름을 계산하기 전에:

--_r: calc((var(--_w) - var(--_sz)) / 2);
둥근 가장자리를 따라 시간 번호 레이블이 있는 큰 토마토 색 원.

훨씬 낫다! 더 우아하게 보이도록 색상을 변경해 보겠습니다.

어두운 회색 배경에 숫자가 있는 흰색 시계 문자판. 시계에는 팔이 없습니다.

여기서 멈출 수 있습니다! 우리는 원 주위에 텍스트를 배치하는 목표를 달성했습니다. 맞습니까? 그러나 시간, 분, 초를 표시하는 팔이 없는 시계는 무엇입니까?

이를 위해 단일 CSS 애니메이션을 사용하겠습니다. 먼저 마크업에 세 가지 요소를 더 추가해 보겠습니다.

<div class="clock"> <!-- after <time>-tags --> <span class="arm seconds"></span> <span class="arm minutes"></span> <span class="arm hours"></span> <span class="arm center"></span>
</div>

그런 다음 세 팔 모두에 대한 몇 가지 공통 마크업이 있습니다. 다시 말하지만, 이것의 대부분은 팔이 절대적으로 배치되고 그에 따라 배치되는지 확인하는 것입니다.

.arm { background-color: var(--_abg); border-radius: calc(var(--_aw) * 2); display: block; height: var(--_ah); left: calc((var(--_w) - var(--_aw)) / 2); position: absolute; top: calc((var(--_w) / 2) - var(--_ah)); transform: rotate(0deg); transform-origin: bottom; width: var(--_aw);
}

우리는 같은 애니메이션 세 팔 모두:

@keyframes turn { to { transform: rotate(1turn); }
}

유일한 차이점은 개별 팔이 완전히 회전하는 데 걸리는 시간입니다. 을 위해 시간 팔, 걸립니다 12 시간 완전한 회전을 하기 위해. 그만큼 animation-duration 속성은 밀리초와 초 단위의 값만 허용합니다. 43,200초(60 seconds * 60 minutes * 12 hours).

animation: turn 43200s infinite;

그것은 1 시간 위한 분 팔 완전한 회전을 하기 위해. 그러나 우리는 이것이 다단계 애니메이션 따라서 팔 사이의 움직임은 선형이 아니라 엇갈리게 움직입니다. 분당 하나씩 60단계가 필요합니다.

animation: turn 3600s steps(60, end) infinite;

XNUMXD덴탈의 초 팔 is 거의 같다 분 암으로 사용되지만 지속 시간은 60분이 아닌 60초입니다.

animation: turn 60s steps(60, end) infinite;

공통 스타일에서 생성한 속성을 업데이트해 보겠습니다.

.seconds { --_abg: hsl(0, 5%, 40%); --_ah: 145px; --_aw: 2px; animation: turn 60s steps(60, end) infinite;
}
.minutes { --_abg: #333; --_ah: 145px; --_aw: 6px; animation: turn 3600s steps(60, end) infinite;
}
.hours { --_abg: #333; --_ah: 110px; --_aw: 6px; animation: turn 43200s linear infinite;
}

현재 시간에 시작하려면 어떻게 해야 합니까? 약간의 JavaScript가 필요합니다.

const time = new Date();
const hour = -3600 * (time.getHours() % 12);
const mins = -60 * time.getMinutes();
app.style.setProperty('--_dm', `${mins}s`);
app.style.setProperty('--_dh', `${(hour+mins)}s`);

나는 추가했다 id="app" 음수를 설정하는 두 개의 새로운 사용자 지정 속성을 설정합니다. animation-delay, Mate Marschalko가 한 것처럼 그가 CSS 전용 시계를 공유했을 때. 그만큼 getHours() JavaScipt의 메소드 Date 객체는 24시간 형식을 사용하므로 remainder 연산자 12시간 형식으로 변환합니다.

CSS에서 다음을 추가해야 합니다. animation-delay 게다가:

.minutes { animation-delay: var(--_dm, 0s); /* other styles */
} .hours { animation-delay: var(--_dh, 0s); /* other styles */
}

한 가지 더. CSS 사용 @supports 우리가 이미 생성한 속성을 지원하지 않는 브라우저에 폴백을 제공할 수 있습니다. sin() 과 cos(). (Temani Afif, 감사합니다!):

@supports not (left: calc(1px * cos(45deg))) {
  time {
    left: 50% !important;
    top: 50% !important;
    transform: translate(-50%,-50%) rotate(var(--_d)) translate(var(--_r)) rotate(calc(-1*var(--_d)))
  }
}

그리고 짜잔! 우리 시계가 완성되었습니다! 여기 마지막 데모가 한 번 더 있습니다. 다시 말하지만 현재로서는 Firefox와 Safari에서만 지원됩니다.

우리는 무엇을 더 할 수 있습니까?

그냥 여기저기 돌아다녀도 시계를 원형 이미지 갤러리로 빠르게 바꿀 수 있습니다. <time> 태그 <img> 그런 다음 너비를 업데이트합니다(--_w) 및 반지름(--_r) 값:

하나 더 시도해 봅시다. 앞에서 시계가 어떻게 현대 미술 실험처럼 보이는지 언급했습니다. 우리는 그것에 기댈 수 있고 요 전에 아트 갤러리에서 포스터에서 본 패턴(불행히도 구입하지 않은)을 다시 만들 수 있습니다. 내가 기억하는 것처럼 그것은 "달"이라고 불렸고 원을 형성하는 점들로 구성되었습니다.

다양한 흙색의 채워진 작은 원들로 구성된 큰 원.

원이 특정 순서를 따르지 않기 때문에 이번에는 순서가 지정되지 않은 목록을 사용합니다. 모든 목록 항목을 마크업에 넣지는 않을 것입니다. 대신에 JavaScript를 주입하고 최종 결과를 조작하는 데 사용할 수 있는 몇 가지 컨트롤을 추가해 보겠습니다.

컨트롤은 범위 입력(<input type="range">) 우리는 <form> 그리고 들어 input 행사.

<form id="controls"> <fieldset> <label>Number of rings <input type="range" min="2" max="12" value="10" id="rings" /> </label> <label>Dots per ring <input type="range" min="5" max="12" value="7" id="dots" /> </label> <label>Spread <input type="range" min="10" max="40" value="40" id="spread" /> </label> </fieldset>
</form>

우리는 "input"에서 이 메소드를 실행할 것입니다. <li> 정도가 있는 요소(--_d) 이전에 사용한 변수를 각각 적용했습니다. 반지름 변수의 용도를 변경할 수도 있습니다(--_r).

나는 또한 점들이 다른 색이기를 원합니다. 그래서, 무작위화하자(글쎄, 아니 완전히 무작위) 각 목록 항목에 대한 HSL 색상 값을 새 CSS 변수로 저장합니다. --_bgc:

const update = () => { let s = ""; for (let i = 1; i <= rings.valueAsNumber; i++) { const r = spread.valueAsNumber * i; const theta = coords(dots.valueAsNumber * i); for (let j = 0; j < theta.length; j++) { s += `<li style="--_d:${theta[j]};--_r:${r}px;--_bgc:hsl(${random( 50, 25 )},${random(90, 50)}%,${random(90, 60)}%)"></li>`; } } app.innerHTML = s;
}

XNUMXD덴탈의 random() 메서드는 정의된 숫자 범위 내에서 값을 선택합니다.

const random = (max, min = 0, f = true) => f ? Math.floor(Math.random() * (max - min) + min) : Math.random() * max;

그리고 그게 다야. JavaScript를 사용하여 마크업을 렌더링하지만 렌더링되는 즉시 실제로 필요하지 않습니다. 그만큼 sin()cos() 함수는 올바른 위치에 모든 점을 배치하는 데 도움이 됩니다.

마무리

원 주위에 물건을 놓는 것은 다음과 같은 삼각 함수의 힘을 보여주는 매우 기본적인 예입니다. sin()cos(). 그러나 그것은 정말 이전 해결 방법에 대한 새로운 솔루션을 제공하는 최신 CSS 기능을 사용하고 있다는 사실이 놀랍습니다. 특히 브라우저 지원이 Chrome 및 Edge에 제공됨에 따라 훨씬 더 흥미롭고 복잡하며 창의적인 사용 사례를 보게 될 것이라고 확신합니다.

타임 스탬프 :

더보기 CSS 트릭

천체

소스 노드 : 845518
타임 스탬프 : 2021 년 5 월 5 일