ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • SVG 왕초보와 함께하는 그래프/차트 만들기 - 2. 직선, 곡선 그래프
    토막글 2021. 8. 2. 13:38

    안녕하세요 :)

    이번엔 SVG로 곡선 그래프를 만들어본 경험을 공유해보려 합니다.

     

    앞서 SVG 왕초보와 함께하는 그래프/차트 만들기 - 1. 도넛 차트 를 읽고 오신 분이 아니라면, 해당 글에서 설명했던 내용들이 비슷하게 다시 나오기 때문에 도넛 차트를 구현하실 분이 아니더라도 읽고 와주시면 더 이해가 빠를거예요! 다만 d attribute의 A command는 안 쓸거니 스킵하셔도 됩니다. (해당 글 2번 섹션에 있음)

     

    이번에도 결과부터 보자면, 왼쪽의 데이터가 오른쪽 차트로 보이게 됩니다.

     

    구현 순서

    구현 순서를 요약해 말해보자면 다음과 같습니다. 요번엔 3번이 고비예요

    1. 데이터를 그래프 좌표로 변환하기
    2. 직선 그래프 그려보기
    3. 곡선 그래프를 위한 control point 만들기 (control point가 뭐지...? 느껴지셔도 일단 스킵!)
    4. 곡선 그래프 그리기
    5. 애니메이션

     

    1. 데이터를 그래프 좌표로 변환하기

    저희가 받은 데이터는 각 날짜 순서대로 소비한 금액이 들어오게 됩니다. 위의 데이터 기준으로, 1일 소비 금액은 20000원, 2일은 100000원, ... 처럼 되는거죠. 그래프는 x 축이 날짜, y축이 금액이므로 해당 좌표계에 맞게 데이터를 좌표로 변환해줘야 합니다.

    x 축은 날짜, y 축은 금액

    x축을 먼저 설명해보자면, 만약 한 달의 최대 날짜가 30이라면 각 사이의 간격은 29개가 될 것입니다.

    따라서, SVG width를 29개 만큼 나눈 값을 구하고, 거기에 index를 곱한 값이 x 좌표가 됩니다.

     

    y축에 해당하는 데이터는 가격입니다. 이 가격을 데이터 내의 최대 값으로 나누면 데이터 내의 percentage 가 될 것입니다. 여기에 SVG 의 height을 곱하면 y좌표가 되겠죠! 코드로 옮기면 다음과 같습니다.

     

     

    getCoordinates에 data를 넣고 얻은 결과는 아래와 같습니다.

    SVG 내의 x, y 좌표

    2.  직선 그래프 그려보기

    앞서 getCoordinates 함수로 우린 데이터의 좌표를 얻었습니다. 이 좌표로 직선 그래프를 그려보도록 하죠!

    우린 path d attribute의 M, L 명령어를 사용할 것입니다.

     

    SVG 의 <line> 태그를 사용해서도 이를 표현할 수 있겠지만 해당 차트에선 이를 표현하려면 29개의 line 태그가 필요하게 될 것입니다.

    path의 d attribute의 M, L 명령어를 사용하면 한 줄로 표현할 수 있습니다.

     

    M (x, y) 는 시작점을 정해주고, L (x, y)는 해당 좌표로 선을 그을 수 있게 됩니다.

    그렇다면 데이터의 좌표를 순회하며 처음 좌표라면 M 명령어를, 나머지 좌표는 L 명령어를 추가해주면 되겠군요!

    아래는 코드와 그 결과값입니다 :)

    이쁘다 이뻐

     

    3.  곡선 그래프를 위한 Control Point 만들기

    사실 저 정도만 해도 저희는 행복합니다. 그러나 아시죠?

    저는 곡선으로 그래프를 표현하고 싶었고, 이는 재앙의 시작이었습니다. 근데 사실 그렇게 안어려워요 ^,.^

     

    d attribute 에선 Bezier curve를 그릴 수 있게 해주는 C 명령어가 있습니다.

    이 명령어는 다음 6개의 인자를 받습니다. C (x1, y1, x2, y2, x, y) 

    x, y는 우리가 익히 아는 목표 지점입니다. 그렇다면 (x1, y1), (x2, y2)는 뭘까요?

    이는 bezier curve의 control point를 지정해주는 값입니다.

    4개의 control point로 표현한 Cubic Bezier curve

    아래 그림과 같이, bezier curve를 그리기 위해선 총 4개의 점이 필요합니다.

    우린 시작, 끝점을 이미 알고 있으므로, 나머지 2개의 점이 필요한데요. 해당 점을 Control Point라 지칭합니다.

    아마 해당 링크로 들어가셔서 몇 번 만져보시면 바로 감이 오실겁니다.

     

    이 점을 구하기 위해선 다음과 같은 절차가 필요합니다.

    우리는 S1 (E0), E1 (S2) 를 알고 있습니다.

    즉, 끝점은 시작점의 다음 점, 시작점은 끝점의 이전 점이 되는거죠. (말이 어렵죠... 이것 말고 다른 표현이 생각이 안나네요 ㅜ)

     

    자세히 보시면, CP1은 S0에서 S2로 이은 선과 평행한 선 위에 있습니다. 이를 양의 방향으로 일정 거리에 해당하는 점이 CP1인 거죠!

    CP2는 E0에서 E2로 이은 선과 평행하며 반대로 음의 방향으로 일정 거리에 해당하는 점입니다.

    이 일정거리를 얼마나 늘리느냐에 따라 더 smooth 한 곡선이 만들어지게 됩니다.

     

    아까 말한 S0, S2로 이은 선과, E0, E2로 이은선을 opposedLine이라고 지칭합니다. 그리고 opposedLine의 길이, x축으로부터의 각도를 구해야 합니다.

    한번 코드로 옮겨보죠!!

     

    피타고라스의 정리에 의하여 length는 각 좌표의 x, y 길이의 제곱의 제곱근입니다.

    각도는 atan2 method를 사용하면 쉽게 구할 수 있습니다 :)

    해당 정보들을 사용해 Control Point 를 구하면 됩니다!

     

     

    앞서 말했다시피 Contorl Point는 두개가 있는데, 만약 끝 CP 일 경우 음의 방향으로 만들어 주어야 합니다. 따라서 angle에 Math.PI를 곱해줍니다.

     

    4. 곡선 그래프 그리기

    드디어 곡선 그래프를 그립니다!!

    우리는 앞선 연산들로부터 C command를 위한 모든 정보를 이미 알고 있습니다.

    시작점, 끝점, Control Point 1, 2를 모두 알고있죠.

     

    이를 나열하기만 하면 됩니다!!

    우선 path의 d 속성이 가질 값을 구하는 코드를 보도록 하죠.

     

     

    각각 control point start X, Y, End X, Y, 끝점을 넣어주면 됩니다.

     

    그리고 return 값을 d value 값에 넣어주면 됩니다 :)

    아래는 곡선 차트를 그리는 함수입니다.

    style은 stroke-width 때문에 곡선이 차트 바깥으로 빠져 나오게 되므로, 이를 조정하기 위한 스타일 코드입니다.

     

    5. 애니메이션

    거의 끝나갑니다 !!

    해당 글을 보시기 전에 SVG 왕초보와 함께하는 그래프/차트 만들기 - 1. 도넛 차트 를 읽어보셨다면 stroke-dasharray, stroke-dashoffset에 대해 이해하고 계실 것입니다. 이번에도 이 속성을 사용해 구현합니다. 

     

    원리는 같습니다. path의 길이만큼 stroke-dashoffset을 당겨놓았다가, 0만큼 이동시키면 됩니다.

    문제는 글에서는 percentage 가 있었기 때문에 해당 percentage 만큼 호의 길이를 알아낼 수 있었습니다.

    그러나 이번에는 해당 정보가 없습니다 :( 우리는 어떻게 path의 길이를 알아내야 할까요?

     

    path 내에는 getTotalLength() 라는 메소드가 있습니다.

    해당 메소드를 사용하면 path 의 길이를 알 수 있고, 우리는 해당 길이만큼 dashoffset을 주었다가 0으로 돌려주면 되겠죠!

    아래는 해당 코드입니다 :)

     

     

    stroke-dasharray 속성을 주고, dashoffset을 path.getTotalLength() 만큼 주고 0으로 돌려줍니다.

    드디어 우리가 원했던 곡선 차트를 완성했습니다~~ 

     

    짝짝짝

     

    마무리

    예시 gif 에 있는 기준선은 굳이 설명하지 않겠습니다. line 태그를 이용해 쉽게 만들 수 있습니다.

    몇일 전까지만해도 SVG 생초보였는데, 앞의 도넛 차트와 곡선 그래프를 구현하며 약간의 자신감을 얻을 수 있었습니다 :)

     

    참고 자료

     

    Bézier curve - Wikipedia

    From Wikipedia, the free encyclopedia Jump to navigation Jump to search Curve used in computer graphics and related fields Cubic Bézier curve with four control points The basis functions on the range t in [0,1] for cubic Bézier curves: blue: y = (1 − t

    en.wikipedia.org

     

    Smooth a Svg path with cubic bezier curves

    And a bit of trigonometry

    francoisromain.medium.com

     

    SVG Cubic Bézier Curve Example

     

    blogs.sitepointstatic.com

     

    댓글

Designed by Tistory.