progress circle UI 컴포넌트 만들기
sapa 로 UI 만드는 중에 progress circle 컴포넌트를 만들게 되었습니다.
원래는 따로 만들지 않을려고 했는데, 다른 UI 컴포넌트 중간 중간에 로딩 상태를 표현 해야하는 부분들이 있어서 작게 만들었습니다.
기본적으로 svg의 circle 을 사용하고 있고 stroke-dasharray 로 offset 을 맞춥니다.
사이즈는 정사각형으로 고정(width)입니다. min, max, value 에 따라서 offset 을 구할 수 있습니다.
offset = (value - min) / (max - min);
여기까지는 js 영역인데요. css 의 기능들이 조금 더 필요합니다.
----
offset 을 기준으로 stroke-dasharray 를 자동으로 표현할려면 어떻게 할 수 있을까요? 이 때부터는 css variable 이 힘을 발휘 합니다.
circle 은 small, medium, large, extra-large 의 크기를 가집니다.
각 크기마다 width 가 정의되어 있습니다. 그리고 stroke-width 도 정의 되어 있습니다. 이 말은 circle 의 크기마다 stroke-width 도 같이 영향을 받는다는 말입니다.
처음에는 width 기준으로만 원을 계산 했습니다.
이러다 보니 offset 이 자꾸 넘어가는 현상이 나왔다.
(stroke-dasharray 에 정의된 크기가 안 맞아서 원을 가득 채우게 되는 현상)
왜인지 몰라서 한참 생각하다 보니 circle 에서 stroke 가 중심을 기준으로 커진다는게 생각났다.
svg 크기가 50 x 50 으로 되어 있을 때 circle 도 25, 25 형태로 맞추면
svg 박스를 벗어나면서 그리는게 아니라 박스 안에 circle 을 그리게 되기 때문에
stroke 가 굵어지면 실제로 box 보다 작은 원을 기준으로 그리게 됩니다.
그래서 최종적으로 css 코드를 맞춰보면 아래와 같습니다.
// calculate svg circle size (width - bar-height) is circle raidus
--progress-circle-size: calc(var(--elf--progress-circle-width) - var(--elf--progress-circle-bar-height));
// stroke total length
--progress-total-length: calc(var(--progress-circle-size) * var(--math-pi));
// stroke offset length
--progress-gauge: calc(var(--progress-total-length) * var(--elf--progress-circle-offset));
stroke-dasharray: var(--progress-gauge) calc(var(--progress-total-length) - var(--progress-gauge));
(gauge) 크기와 (전체 - gauge) 크기를 맞추면 css 만 가지고 gauge 를 그릴 수 있게 됩니다.
ps.
참고로 --math-pi 는 따로 없기 때문에 아래와 같이 정의해서 쓰시면 됩니다.
:root { --math-pi: 3.141592653589793; }
댓글
로그인 후 댓글을 남길 수 있습니다.
아직 댓글이 없습니다.