728x90
반응형

포트폴리오 디자인을 전부 갈아엎는 과정에서 about me 파트와 modal창에 사용된 가로 차트(horizon chart)와 원형 차트(circle)가 창이 로딩된 후 숫자가 차르륵 올라가는 효과를 어떻게 구현했는지 기록하려고 한다.

 

원형 차트의 숫자가 움직이는 효과를 구현하면서 가로 차트도 이렇게 숫자가 차르륵 올라가면 예쁠텐데, 하고 생각했지만 가로 차트를 만드는 유튜브 영상을 과장 좀 보태서 수십 개를 찾아봐도 숫자가 0, 1, 2 ~ 99, 100 하고 올라가는 효과를 구현해둔 건 찾아볼 수가 없어서 가로형 차트는 css로만 구현해야 하나 싶었다.

그 때 머리를 스치는 생각이 원형 차트를 만드는 방식을 따라해서 가로형 차트의 가상 요소 after 값을 원형 차트가 작동하는 방식으로 바꿔주면 되지 않을까?  였다.

그 예상은 멋드러지게 적중하여 나는 움직이는 원형 차트와 가로형 차트를 얻은 것이다.

 

 

 

일단 원형 차트를 만든 과정부터 시작해보겠다.

 

원형 차트 완성본

 

<div class="circle" data-degree="87" data-color="#d271fe">
  <h2 class="circle_number">87<span>%</span></h2>
  <h4 class="circle_title">css</h4>
</div>
<div class="circle" data-degree="90" data-color="#d271fe">
  <h2 class="circle_number">90<span>%</span></h2>
  <h4 class="circle_title">html</h4>
</div>
<div class="circle" data-degree="75" data-color="#d271fe">
  <h2 class="circle_number">75<span>%</span></h2>
  <h4 class="circle_title">javascript</h4>
</div>
<div class="circle" data-degree="80" data-color="#d271fe">
  <h2 class="circle_number">80<span>%</span></h2>
  <h4 class="circle_title">framework</h4>
</div>

 

원형 차트 완성본 이미지를 보면 data-degree 값과 %의 숫자가 같다는 걸 알 수 있다.

즉, data-degree 값만큼만 숫자가 증가하면서 원형 차트가 차오르는 것이다.

 

숫자가 증가하는 효과는 javascript(자바스크립트)로 구현했으니 자바스크립트도 살펴보자.

 

let circle = document.querySelectorAll(".circle");
  circle.forEach(function (progress) {
    let degree = 0;
    let targetDegree = parseInt(progress.getAttribute("data-degree"));

    let color = progress.getAttribute("data-color");
    let number = progress.querySelector(".circle_number");

    let interval = setInterval(function () {
      degree += 1;

      if (degree > targetDegree) {
        clearInterval(interval);
        return;
      }

      progress.style.background = `conic-gradient(${color} ${degree}%, #222 0%)`;
      number.innerHTML = degree + `<span>%</span>`;
      number.style.color = color;
    }, 50);
  });

 

let degree = 0;

: degree 변수는 애니메이션이 진행될 때 현재 원형 차트의 배경이 얼마나 채워졌는지를 나타내는 값이다. 물론 초기값은 0이다. 

 

let targetDegree = parseInt(progess.getAttribute("data-degree")

: data-degree 라는 커스텀 데이터 속성에서 값을 가져와 숫자로 변환하여 targetDegree 변수에 저장하는 구문이다.

목적은 애니메이션이 종료될 때 배경이 채워질 목표 각도를 설정하는 것이다.

 

color는 원형 차트에 어떤 색을 적용할 것인지에 대한 hex 값을 가져오는 것이니 별로 신경 쓰지 않아도 된다.

 

✏ getAttribute 

:자바스크립트에서 DOM  요소의 특정 속성(attribute) 값을 가져오는 메서드이다.

이 메서드를 사용하면 HTML 요소에 설정된 특정 속성의 값을 읽을 수 있다.

 

let interval = setInterval(funtion () { ... } , 50);

: setInterval을 사용하여 50 밀리초마다 반복해서 실행되는 함수 즉, 애니메이션 루프를 설정하는 구문이다.

목적은 원형 배경이 채워지는 애니메이션을 구현하기 위해 주기적으로 코드를 실행하는 것이다.

 

degree += 1

: 현재의 degree 값을 1씩 증가 시키는 구문이다.

애니메이션이 진행될 수록 원형 배경을 점진적으로 채우기 위해 각도를 증가시키는 역할을 한다.

 

if (degree < targetDegree) { clearInterval(interval); return)

:현재의 degree 값이 목표 각도(targetDegree)를 초과하면 애니메이션을 멈추게 하는 구문이다.

즉, 목표 각도에 도달하면 애니메이션을 종료하게 만든다.

값과 다르게 원이 꽉꽉 들어차는 걸 보고 싶지 않다면 꼭 넣는 게 좋은 구문이다.

 

progress.style.background = \`conic-gradient(${color} ${degree}%, #222, 0%)

:CSS의 conic-gradient를 사용해 배경이 원형으로 채워지도록 설정하게 하는 구문이다.

여기서 degree의 %만큼 color 값의 색으로 채워지고 나머지는 #222(어두운 색)으로 표시된다.

즉, 원형 배경을 애니메이션에 따라 점차적으로 채워지는 효과를 시각적으로 표현하는 것이다.

 

number.innerHTML = degree + \`<span>%</span>

: 현재의 degree 값을 html로 삽입하여 원형 내부에 표시하는 구문이다. 이때 %도 함께 표시된다.

 

 

여기서 progress.style.background = \`conic-gradient(${color} ${degree}%, #222, 0%) 를 보자.

방금은 원형이라 conic-gradient를 사용했지만 가로형 차트를 구현한다면 conic-gradient를 사용할 필요가 없다.

여기만 가로형 차트의 width 값이 되는 것으로만 바꿔준다면 어디서 본 건 있는 나의 욕구를 충족 시켜줄 수 있는 코드를 구현할 수 있다는 뜻이다.

 

 

 

겨우 본론으로 돌아와서, 가로형 차트를 살펴보자.

가로 차트 완성본

 

이게 멋드러지는 가로형 차트의 완성본이다.

다시 생각해도 뿌듯해서 자꾸 보게 된다.

 

 

이제 가로형 차트의 html을 보자

<div class="chart_line" chart-data-degree="85">
  <span class="skill_name">react</span>
  <div class="chart_bar"></div>
  <span class="percent">0<span>%</span></span>
</div>
<div class="chart_line" chart-data-degree="75">
  <span class="skill_name">vite</span>
  <div class="chart_bar"></div>
  <span class="percent">0<span>%</span></span>
</div>
<div class="chart_line" chart-data-degree="78">
  <span class="skill_name">php</span>
  <div class="chart_bar"></div>
  <span class="percent">0<span>%</span></span>
</div>
<div class="chart_line" chart-data-degree="83">
  <span class="skill_name">vue</span>
  <div class="chart_bar"></div>
  <span class="percent">0<span>%</span></span>
</div>
<div class="chart_line" chart-data-degree="80">
  <span class="skill_name">next.js</span>
  <div class="chart_bar"></div>
  <span class="percent">0<span>%</span></span>
</div>
<div class="chart_line" chart-data-degree="65">
  <span class="skill_name">redux</span>
  <div class="chart_bar"></div>
  <span class="percent">0<span>%</span></span>
</div>

 

원형 차트랑 구조는 같다. (사소한 건 다르지만) 

기본적인 뼈대(틀)은 같다.

차트 전체를 구성하는 div 박스에 data-degree, 즉 차트가 채워질 만큼의 커스텀 데이터 값이 있고, 각 차트의 타이틀과 어떤 제목을 가졌고, 출력될 % 값이 있다.

 

차이점은 원형 차트에는 width 값이 필요가 없었는데 가로형 차트(horizon chart)에는 width 값이 필요하다는 것이다.

.chart_line {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-right: 10%;

    .skill_name {
      width: 10%;
      text-transform: uppercase;
      letter-spacing: 0.5vw;
    }

    .chart_bar {
      display: flex;
      width: 35vw;
      height: 1.5vw;
      background-color: rgba(255, 255, 255, 0.5);
      position: relative;

      &::after {
        content: "";
        position: absolute;
        background-color: #d271fe;
        width: var(--progress-width, 0%);
        height: inherit;
        top: 0;
        left: 0;
        z-index: 1;
        transition: width 1s ease;
      }
    }
}

 

이런 식으로 말이다.

여기서 

배경의 불투명한 부분이 chart_bar가 된다. 전체적인 가로형 차트의 배경을 그리고 가상 요소(::after)를 사용하여 그 위를 덮는 형식으로 가로형 차트를 구현했다.

그러니까 chart_bar의 width 값은 건드리지 않고 ::after의 width 값에만 변화를 주어야 하는 것이다.

그것도 값이 전부 다 다른 여섯 개의 차트를 말이다.

 

그래서 찾은 방법이 --progress-width를 사용하는 것이었다. 

css의 커스텀 속성인 --progress-width를 사용하여 프로그레스 바의 너비를 조절하는 방법이다.

이를 사용하면 차트의 chart-data-degree 값을 따라 달라지게 되는 것이다.

 

그래서 자바스크립트를 어떻게 짰냐면,

 let chartLines = document.querySelectorAll(".chart_line");
  chartLines.forEach(function (progress) {
    let degree = 0;
    let targetDegree = parseInt(progress.getAttribute("chart-data-degree"));

    let bar = progress.querySelector(".chart_bar");
    let percent = progress.querySelector(".percent");

    let interval = setInterval(function () {
      degree += 1;

      if (degree > targetDegree) {
        clearInterval(interval);
        return;
      }

      bar.style.setProperty("--progress-width", degree + "%");
      percent.innerHTML = degree + `<span>%</span>`;
    }, 50);

 

원형 차트의 자바스크립트 틀을 그대로 가져왔다.

물론 필요없는 color는 빼버렸다.

 

원형 차트와 똑같이 let chartLines를 document.quertSelectorAll을 사용하여 .chart_line이라는 클래스를 가진 모든 요소를 선택하고, 여러 개인 chartLines에 forEach를 사용하여 각 요소에 대해 순회하면서 콜백함수를 실행할 수 있도록 했다.

여기서의 progress는 각각의 .chart_line이 되겠지.

 

let degree = 0으로 degree의 초기값을 0으로 설정했다.

의외인 점은 let이 변수 선언이라지만 원형 차트도, 가로형 차트도 전부 degree라는 변수를 사용했는데 꼬이지 않고 값들이 제자리를 쏙쏙 찾아 들어갔다는 점이다.

data-degree 값을 찾아서 집어넣는 방식이라 그런가.

 

어쨌든,

let targerDegree = parseInt(progress.getAttribute("chart-data-degree")) 를 사용하여 커스텀 데이터 속성에서 값을 가져와 targetDegree 변수에 저장하게 만든다.

아, 아까는 data-degree였는데 왜 지금은 chart-data-degree를 사용하냐면, 내가 헷갈리기 때문이다. 별 이유는 없다.

 

let bar = progress.querySelector(".chart_bar)를 사용하여 .chart_bar 클래스를 가진 자식 요소를 선택하여 bar에 저장한다.

왜냐면 프로그레스 바의 시각적 요소를 조작하기 위해서이다.

 

let percent = progress.querySelector(".percent")를 사용하여 percent 클래스를 가진 자식 요소를 선택하여 percent 변수에 저장한다. 진행도를 텍스트로 표시할 요소를 선택하여 애니메이션 중 업데이트 할 수 있도록 하기 위해서이다.

대충 숫자가 차르륵 올라가려면 이 과정이 꼭 필요하다는 것만 알아두자.

 

let interval = setInteval( function ( ) { ... }, 50) 

아까처럼 setInterval을 사용해 50밀리초마다 반복해서 실행되는 함수(애니메이션 루프)를 설정한다. 프로그레스 바가 점진적으로 채워지는 애니메이션을 구현하기 위해 주기적으로 코드를 실행해야 하기 때문이다.

 

degree += 1을 사용하여 애니메이션이 진행될 수록 프로그레스 바를 점진적으로 채우기 위해 현재의 degree 값을 1씩 증가시키고, if (degree > targetDegree) {clearInterval(interval); return;)을 사용해 현재의 degree 값이 목표 진행도(targetDegree)를 초과하면 clearInterval로 애니메이션을 멈춘다.

 

bar.style.setProperty("--progress-width", degree + "%");

:CSS의 커스텀 속성(progress-width)을 설정하여 프로그레스 바의 width값을 조정하게 된다. degree 값에 따라 width가 점진적으로 증가하게 한다.

프로그레스 바의 시각적 진행 상태를 업데이트하여 애니메이션 효과를 만들게 하는 것이다.

 

✏  setProperty

: 자바스크립트의 CSS Style Declaration 객체에서 사용되는 메서드로, CSS 변수(커스텀 속성 ex.progree-width)를 설정하거나 일반 CSS 속성의 값을 변경하는데 사용됨. 이 메서드는 주로 element(요소).style을 통해 접근할 수 있으며, CSS 변수의 값을 동적으로 변경할 때  유용함.

 

percent.innerHTML = degree + \`<span>%</span>`

:현재의 degree 값을 HTML로 삽입하여 프로그레스 바  옆에 진행도를 퍼센트로 표시하는 구문이다. 숫자가 차르륵 올라가려면 이 과정이 필수이다.

 

 

이 모든 과정을 거치고 나면 숫자라 차르르르르륵 올라가는 쾌감이 엄청난 차트 바와 원형 차트를 만들 수 있는 것이다.

사실 내가 언젠가 또 써먹고 싶은데 기억 안 나서 헤맬까봐  써놓는 것이다.

뭐... 나처럼 짱 멋진 가로형 차트를 만들고 싶은데 방법을 모르겠는 사람이 보면 더 좋고.

 

+ Recent posts