본문 바로가기

UI 디자인 애니메이션 연구소

HTML+CSS+JS 를 이용한 써클 프로그래스 애니메이션을 만들어 봅시다

반응형

이전 애니메이션

 

CSS +JS 를 이용한 톡톡 튀는 폭죽(스파크) 애니메이션 만들기

이전 애니메이션 | 로딩 스피너 HTML/CSS 를 이용한 로딩 스피너 만들기3탄 | 마우스 호버 시 따라다니는 언더라인 만들기 바닐라 JS/HTML/CSS 로 재밌는 애니메이션 효과 만들기 (3탄)2탄 | HTML/CSS 만

duklook.tistory.com

 

미리보기

이 포스트를 따라오시면 아래와 같은 프로그래스 애니메이션을 구현하실 수 있는 능력을 가지게 됩니다.

 

 

 

HTML

우선 마크업을 만들어 줍니다. 필요한 마크업은 프로그래스의 트리거 역할을 하는 button 과 프로그래스 역할을 하는 div, span 이 필요 합니다. 크게 건드릴 부분은 없으므로 이대로 적어 줍니다.

<button class='charge_btn'>충전하기</button>
<div class="circle">
  <span class="percentage">0%</span>
</div>

 

 

CSS

CSS 초기화

CSS 에서는 제일 먼저 기본으로 설정된 여백을 제거하기 위해 margin 과 padding 을 0 으로 지정 합니다. box-sizing 은 border-box 로 지정하여 padding 과 margin 의 사이즈가 컨텐츠 박스의 사이즈 계산 시 반영되도록 설정해줍니다. 

* {
  margin:0;
  padding:0;
  box-sizing:border-box;
}

 

box-sizing 의 이해가 어려운 경우이 사이트( https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing ) 를 참고해주세요. 

 

써클 중앙정렬

body {
  background:#2884E8;
  height:100vh;
  display:flex;
  justify-content:center;
  align-items:center;
}

 

.circle 이 부여된 태그가 화면의 중앙에 올 수 있도록 그 부모 태그인 body 태그에 display 를 flex 로 지정하고, justify-content 와 align-items 를 center 로 각각 지정하여 수직/수평 모두 중앙으로 정렬이 되도록 설정해줍니다. 참고로 flex 가 적용된 요소의 정렬 기준은 해당 요소의 넓이와 높이를 기준으로 하기 때문에, height를 100vh 로 지정하여 body 태그가 브라우저 뷰포트의 100%를 차지하도록 설정해주어야 요소가 중앙에 정상적으로 정렬됩니다.

 

써클 꾸미기 및 써클의 퍼센티지 원리

이제 본격적으로 써클을 꾸며 줍시다.

.circle {
  --percentage:0;
  display:flex;
  justify-content:center;
  align-items:center;
  border-radius:50%;
  width:200px;
  background:conic-gradient(orange calc(3.6deg * var(--percentage)), #69a9ef 0deg);
  height:200px;
  position:relative;
}

 

여기서 --percentage 는 사용자 정의 변수 입니다. 향후 JS 를 사용하여 조작할 것이므로 초기값으로 0을 지정해줍니다.

 

display:flex 와 justify-content, align-items 를 위와 같이 지정한 이유는 퍼센티지를 나타내는 span 태그가 해당 요소의 중앙에 정렬이 되도록 설정하기 위해서 입니다.

 

border-radius 는 50% 로 저징하여 현재 요소를 둥근 형태로 만들어주고, width와 height 는 보기 좋게 200px 정도 씩 지정해주었습니다.

 

퍼센티지 렌더링 원리(중요!)

여기서 제일 중요한 속성은 background 의 conic-gradient 라는 메서드 입니다. 코닉은 한글로 원뿔이라는 의미인데, 실제 원뿔과 동일하게 요소의 중앙이 되는 지점을 꼭짓점으로 하여 그라이언트가 입혀지게 됩니다. 현재 우리가 하고자 하는 것은 0deg 부터 360deg 까지 지정한 색상이 채워지도록 하는 것이므로 orange 색상의 시작지점을  최초 0 deg 로 시작해서, percentage 가 100이 되는 지점이 360deg 가 되도록 calc(3.6deg * var(--percentage)) 를 지정해주었습니다. 

calc 와 var
여기서 calc 는 css 에서 제공하는 계산기로서 인자로 전달한 표현식을 계산하여 그 결과를 반환해줍니다. 예를 들어 3.5px * 5 를 전달했다면  17.5px 를 반환해 줍니다.

var 는 앞서 우리가 정의한 --percentage 와 같이 사용자가 정의한 변수에 지정된 값을 반환해주는 메서드 입니다. 즉, --percentage 가 0 이라면 var() 메서드는 0을 반환해줍니다.

 

  background:conic-gradient(orange calc(3.6deg * var(--percentage)), #69a9ef 0deg); 에서 노란색으로 표시한 부분은 그라디언드가 끝나는 지점을 의미합니다. 이를 0deg 로 지정하게 되면, 끝나는 지점이 시작지점과 동일하기 때문에 그라디언트가 생기지 않고 설정한 #69a9ef 색상이 그대로 표시되게 됩니다. 즉, 이를 활용하면 --percentage 가 1씩 증가할 때, orange 가 서서히 차는 효과를 구현할 수 있게 됩니다.

 

percentage 를 표시하는 span 꾸미기

.percentage {
  z-index:1;
  color:white;
  font-size:2.5em;
}

 

이 부분은 크게 신경쓸 것이 없습니다. 그저 화면에 보이는 텍스트가 사용자에게 잘 보일 수 있도록 편하게 꾸며주시면 됩니다. 여기서 z-index 가 중요한데, 이를 1로 지정하지 않으면 absolute 로 지정된 부모 요소의 가시성 순위가 높기 때문에 해당 span 요소가 숨겨져서 보이지 않게 됩니다. 따라서 이를 1로 지정하여 부모 요소의 위에 보여지도록 해준 것입니다.

 

.circle 안 쪽 꾸미기

.circle::before {
  content:'';
  width:160px;
  height:160px;
  left:50%;
  top:50%;
  background:#2884e8;
  border-radius:50%;
  transform:translate(-50%,-50%);
  position:absolute;
}

 

이 부분은 아래 이미지의 빨간색 화살표가 표시하는 영역을 꾸며주는 겁니다.

 

 

::before 을 이용하면, 요소 내부적으로 독립된 스타일을 적용할 수 있는데, 이를 응용한 것입니다. 써클의 내부에 또 다른 써클을 만들어, 이를 중앙에 표시 하기 위해서  position 을 absolute 로 , left 와 top 을 각각 50% 으로 지정합니다. 그 후 transform 의 trsnalate 를 -50%, -50% 으로 지정하여 중앙 정렬 시켜주었고, 그 다음에는 width 와 height 를 적절한 크기로 설정하고, border-radius 를 50% 으로 지정하여 실제 써클 보다는 약간 더 작은 원형을 만들어 주었습니다. 그리고 배경색과 통일성을 주기 위해 background 를 지정한 것이 끝입니다.

 

충전하기 버튼 꾸미기

이 부분은 크게 설명할 것이 없으므로 그대로 넘어 가겠습니다. 앞서 설명을 다 했던 속성이라 이해하기에 무리가 없을 겁니다.

.charge_btn {
  position:absolute;
  left:50%;
  border:none;
  color:white;
  background:rgba(255,255,255,0.3);
  padding:10px;
  top:5%;
  transform:translate(-50%);
  z-index:2;
}

 

JS 작업하기

태그 가져오기 및 초기 셋팅

우선 애니메이션 구현에 필요한 각각의 태그들을 가져와 줍니다.

const circle = document.querySelector('.circle');
const span = document.querySelector('.percentage');
const chargeBtn = document.querySelector('.charge_btn')

 

 

그 다음에는 퍼센티지 상태를 저장할 percentage 변수를 0으로 초기화 해줍니다.

let percentage =0;

 

이벤트 리스너 등록하기

충전하기 버튼에 'click' 이벤트를 등록해주고, 호출 시 increase 함수가 실행되도록 설정해줍니다.

chargeBtn.addEventListener('click',increase)

 

increase 함수 구현하기

이제 increase 함수를 구현해줍니다.

function increase(){
  
  if(percentage<100) {
    ++percentage
    circle.style.setProperty('--percentage',percentage)
    span.textContent=percentage+'%'
    
    requestAnimationFrame(increase)
  } else {
    return alert('충전완료!')
  }
}

 

percentage 가 100이 되는 순간 함수의 호출이 종료되도록 조건을 걸어둡니다. 그리고 조건이 충족되면 else 블록 내의 로직이 실행되어 충전완료 라는 팝업창이 뜨도록 해줍니다.

  if(percentage<100) {... }
  else { return alert('충전완료') }

 

그 후 if 블록 내부에서 조건이 만족할 때 까지 실행할 로직을 작성해주면 됩니다. 여기서 percentage 가 100 까지 증가하도록 ++ 연산자를 변수 앞에 붙여줍니다. 

 ++percentage

 

그 다음 .circle 클래스가 부여된 태그의 style.setProperty 메서드에 접근하여 첫 번째 인자에는 생성할 사용자 정의 변수 이름을 입력해주고, 두 번째 인자에는 해당 변수에 할당할 값을 넣어줍니다. 여기서는 percentage 가 되겠네요.

    circle.style.setProperty('--percentage',percentage)

 

이 다음에는 앞서 증가한 percentage 가 화면의 텍스트에 표시 되도록  span 태그의 textContent 속성에 percentage 를 할당해줍니다. 이 때 textContent는 문자열(string)으로 변환되어 span 태그의 텍스트 노드로 표시 됩니다.

    span.textContent=percentage+'%'

 

조건문 처리의 마지막으로      requestAnimationFrame(increase) 을 추가해줍니다. requestAnimationFrame 은 인자로 전달된 함수를 1초 당 최대 60회 호출합니다. 

    requestAnimationFrame(increase)

 

해당 메서드에 대한 자세한 내용은MDN( https://developer.mozilla.org/ko/docs/Web/API/window/requestAnimationFrame ) 을 참고해보세요.

 

결과

이제 버튼을 클릭하면, 0 ~ 100% 까지 차례대로 퍼센티지가 증가하고, 게이지가 차는 듯한 애니메이션을 확인하실 수 있습니다. 고생하셨습니다.

 

See the Pen 써클 프로그래스 by youngwan2 (@youngwan2) on CodePen.

반응형