svg로 간단한 차트 구현하기

라이브러리 사용 없이 라인/파이 차트 구현해 보기


들어가며

현재 진행 중인 프로젝트에서 차트를 라이브러리를 사용하지 않고 구현할 일이 생겼습니다. 처음으로 svg를 활용해서 두 종류 차트를 구현하게 되었는데 나중에도 간단한 차트일 경우 활용하면 좋을 듯하여 메모를 빙자한 포스팅을 해봅니다.



라인 차트

svg chart line

디자인을 받고 이걸 라이브러리 안 쓰고 어떻게 구현해야 할까 고민했는데, 라인 부분이 떠오르는 게 svg 밖에 없어서 svg polyline을 이용해 라인을 그리게 되었습니다. polyline을 그리는 방식은 points 값에 x,y x,y x,y … 식으로 값을 나열하기만 하면 됩니다. polyline의 스타일은 코드에 직접 입력해도 되지만, 후에 컨트롤이 쉽게 하려면 css에서 컨트롤하는 것이 좋습니다.


svg {
  fill: none;
  stroke: rgba(105, 16, 239, 0.2);
  stroke-width: 4px;
}

stroke: 라인 색상, stroke-width: 라인 두께, fill: none으로 작성하면 깔끔하게 원하는 라인만 그려집니다. 저는 현재 디자인된 차트에서 polyline의 Y 값과 dot 모양 버튼 위치 값이 동일하게 연동되어야 해서 스크립트로 해당 값들을 직접 넣어주게 작성하였습니다. (dot 버튼의 위치값은 % 단위로 작성하였습니다. 디자인된 라인 차트의 높이 값이 200px 이여서 polyline y 값은 dot의 위치값의 2배수로 들어가게 현재 코드는 작성되어 있습니다. 수정해서 사용할 경우 참고해 주세요.)


추가적으로 뭔가 차트 하면 등장 모션 정도는 있어줘야 할거 같아서 svg polyline은 width 사이즈로 모션을 주고, dot 버튼들은 animation을 scale로 주고 라인이 그려지고 난 뒤에 나타날 수 있게 animation duration을 추가하여 작업하였습니다.



파이 차트

svg chart pie

처음엔 쉽게 작업을 해보려고 div로 원형을 그리고 css clip으로 작업해 봤는데 ios에서 position 관련 버그가 생겨 두 번째 파이 차트도 svg로 작업하게 되었습니다. svg circle을 이용해 디자인 대로 모양을 만들고 (저는 180px의 파이 모양을 만들어야 해서 cx=“90” cy=“90” r=“65” 값으로 만들었습니다.)


.pie_circle {
  fill: none;
  stroke-width: 50;
}

fill: none, stroke-width: 파이 차트 두께를 지정해 주면 기본적인 파이 모양이 그려집니다. 그리고 stroke-dashoffset 값과, stroke-dasharray 값을 이용해서 파이 차트를 그려주는데요,


stroke-dasharray 값은 svg의 stroke를 dash로 만들어주는 값이며 값이 클수록 dash 사이의 여백이 커지게 됩니다. stroke-dashoffset 값은 svg의 stroke가 시작되는 위치의 값을 변경하는 데 사용됩니다.


stroke-dasharray의 값을 원의 전체 둘레만큼 주게 되면 꽉 채워진 stroke가 만들어집니다.
전체 원 둘레: (2 * π(파이) * r(반지름))
여기서 stroke-dashoffset 값을 조정하면서 차트 값을 조정할 수 있는데, 20%를 만들려면 전체 원 둘레에서 전체 원 둘레에 20%를 곱한 값을 빼주면 됩니다.
차트 값: (2 * π(파이) * r(반지름)) - (2 * π(파이) * r(반지름) * (20/100))



여기까지 하면 하나의 값이 나오는 파이 차트가 그려집니다. 그런데 우리는 파이가 하나인 차트가 필요한 게 아니죠? 원하는 차트 값만큼 circle을 그리고 각각 값을 위의 식대로 넣어줍니다. 그러면 겹쳐진 circle 같은 위치에서 그려지게 됩니다. 이걸 각각 값에 맞춰 rotate로 각도를 돌려주는 작업이 필요합니다. 예를 들어 1번 값이 50, 20번의 값이 20이라면 1번은 0에서 50까지 채워지지만 2번은 50에서 20만큼 채워져야 합니다. 이 원리를 생각하고 각 값의 rotate를 돌려줍니다.
계산식: 360/100 * 차트 현재 데이터 값의 전 데이터 값



다 그리고 나면 어? 내가 예상한 모양이 아닌데?라는 생각이 들 수도 있습니다. svg가 그려지는 방향이 반시계 방향이거든요, 그래서 저는 css로 좌우 반전을 시켜서 시계방향으로 그려지게 수정하였습니다.


svg {
  transform: scaleX(-1)
}

파이 차트 역시 적절하게 모션을 넣어보려고 했지만 ios 버그가 많았습니다.. 분명 시계방향으로 움직여야 할 모션이 반대쪽으로 움직이고… 해당 부분을 수정할 방법이 없어 모션을 포기하려던 찰나에 꼼수가 살짝 떠올라 bg 용 circle을 하나 더 그리고, 해당 bg circle을 0으로 없애게 하여 차트에 모션을 추가했습니다.

(더 좋은 방법이 있다면 알려주세요!)



마치며

생각보다 꽤 많은 시간을 써서 완성하게 되었지만 라이브러리를 사용하지 않았다는 만족감이 컸던 작업이었습니다. 앞으로는 간단한 차트 정도는 요렇게 그리는 것도 나쁘지 않겠다 생각했지만, 역시 차트 라이브러리는 대단하다는 생각도 같이 드는 작업이었습니다.

참고문서


    추천 글