본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Html 캔버스/Html 캔버스 튜토리얼 (내가만든 차트!)

Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 18 : 원 차트 1

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2020. 2. 20.

 

이번시간부터 부채꼴 모양으로 이루어진 원형 차트를 만드려고한다.

원형 차트는 검색해보면 대략 아래 이미지처럼 생겼다.

구글링하면 나오는 사진들. 대략 부채꼴이 데이터에 맞게 비율로 나온다.

 

사용자가 어떠한 데이터를 입력하면 그 데이터의 전체 합계에서 비율에 맞추어서 차트가 만들어지게 되는 것 이다.

그렇다면 예를들어 첫번째 데이터가 100, 두번째 데이터도 100인 값이 들어왔다고 하자.

두 데이터의 합은 200이며, 그 200중 100이 차지하는 비율은 100/200 = 0.5 이며,

또다른 100이 차지하는 비율은 100/200 = 0.5이다.

위 예로든 데이터가 들어오면 각각 절반씩 채워진 차트가 탄생을 해야 되는 것 이다.

 

이런식으로 데이터가 들어오면 아래 사진처럼 차트가 그려져야 할 것 이다.

비율 사진 예

 

 

이번 원형 차트의 핵심은 이러한 비율을 잘 고려하여 그리는 것이라 볼 수 있다.

또한 캔버스에서는 일반 도(degree)를 사용하지 않고 라디안(radian)을 사용하므로 항상 각도 변환에 대해서 염두해 두어야 한다.

 

그렇다면 데이터가 존재하는 배열을 만들어보자.

그러한 데이터의 비율에 따라서 우리가 사용할 도(degree) 값을 리턴하여 보도록 하자.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Canvas</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<style>
    body{padding: 5%;text-align: center;}
    canvas{border: 1px solid gray;border-radius: 3px;}
</style>
<body>
    <canvas width='400' height='400' id='canvas'></canvas>
</body>
</html>

<script>    
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
   
    var width = canvas.clientWidth;
    var height = canvas.clientHeight;

    var value = [50, 100, 100];
    var degree = 360;
    const radius = 50;

    var sum = value.reduce((a, b) => a + b);  //총합계

    var conv_array = value.slice().map((data)=>{  //conv_array는 비율이 담긴 배열
        var rate = data / sum;  //값을 총합계로 나누어 비율을 구함
        var myDegree = degree * rate;  //비율을 360을(degree) 곱해 비율에 따른 도(degree)를 구함.
        return myDegree;
    });
</script>      

 

50, 100, 100 이라는 데이터를 사용자가 입력하였다고 하자.

간단한 계산을 통해서 conv_array라는 배열에 각각의 비율만큼 도(degree)를 담아주었다.

여기서 50, 100, 100,의 데이터는 비율로 환산하면 72도, 144도, 144도 라는 값이 나오게 된다.

 

이를 정리 해 보면,

첫번째 들어온 데이터는 큰 원형에서 72도만큼 차지해야되고, 다음 데이터는 144도, 마지막 데이터는 144도를 차지하는 모양이 나와야 하는 것 이다.

 

캔버스에서의 원을 그리는 함수는 arc 함수이다.    * 기억이 나지 않으면 : https://lts0606.tistory.com/283

해당 함수에서 시작각과 종료각을 선택할 수 있었는데, 해당 시작각과 종료각을 넣어주면 부채꼴 모양의 그림이 그려지게된다.

conv_array에는 들어온 데이터를 비율에 맞추어서 도(degree)로 변환하였으므로 해당 배열을 활용하면 부채꼴 모양을 그릴 수 있다.

아래 사진의 개념을 먼저 보자.

 

conv_array에서 데이터를 활용해서 부채꼴을 그려야하는데..자세히보면 패턴이 존재한다. "시작 ~ 종료각"

맨 처음만 제외하고선 시작각도가 항상 이전데이터가 포함된 값이라는 것을 볼 수 있다.

이를 규칙으로 반복문을 작성하면,

var degree = 0;
for(var i=0;i < conv_array.length;i++){
    var item = conv_array[i];
    //최초 상태저장이 필요해 보인다.
    if(i == 0){
        degree = item;
        console.log(0, degree);
    } else {
        console.log(degree, degree + item);
        degree =  degree + item;
    }
    //그리기가 필요해 보인다.
}

 

위 내용으로 표현할 수 있다. 실제 동작해보면 시작각과 종료각이 잘 나옴을 볼 수 있다.

잘 나옵니다~

 

그렇다면 주석을 써 놓은 부분에 코드를 조금 수정하여보자.

원을 그리는 함수인 arc를 사용하여 원을 정의하여주고 stroke 또는 fill 을 통해서 원을 그려보도록 하자.

degree = 0;  //초기화

for(var i=0;i < conv_array.length;i++){
    var item = conv_array[i];
    ctx.save();
    ctx.beginPath();
    ctx.moveTo(width/2, height/2);
    if(i == 0){
        ctx.arc(width/2, height/2, radius, (Math.PI/180)*0, (Math.PI/180)* item , false);
        degree = item;
        console.log(0, degree);
    } else {
        ctx.arc(width/2, height/2, radius, (Math.PI/180)*degree, (Math.PI/180)*(degree + item), false);
        console.log(degree, degree + item);
        degree =  degree + item;
    }
    ctx.closePath();
    ctx.stroke();
    ctx.restore();
}

 

arc에서의 x좌표와 y좌표는 캔버스의 중심을 바라보도록 하기 위해서 캔버스 크기의 절반값을 넣어주도록 하였다.

반지름은 여기서 고정값인 50을 주었다.

해당 코드를 실행하면,

짜잔!

 

이상없이 데이터가 비율에 맞추어서 들어간 모습을 볼 수 있다.

당연히 배열에 값을 여러개 넣거나, 크기를 바꾸어도 문제없이 잘 표출되는 것을 볼 수 있다.

 

최종 소스코드이다.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Canvas</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<style>
    body{padding: 5%;text-align: center;}
    canvas{border: 1px solid gray;border-radius: 3px;}
</style>
<body>
    <canvas width='400' height='400' id='canvas'></canvas>
</body>
</html>

<script>    
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext('2d');
   
    var width = canvas.clientWidth;
    var height = canvas.clientHeight;

    var value = [50, 100, 100];
    var degree = 360;
    const radius = 50;

    var sum = value.reduce((a, b) => a + b);  //총합계

    var conv_array = value.slice().map((data)=>{  //conv_array는 비율이 담긴 배열
        var rate = data / sum;  //값을 총합계로 나누어 비율을 구함
        var myDegree = degree * rate;  //비율을 360을(degree) 곱해 비율에 따른 도(degree)를 구함.
        return myDegree;
    });

    degree = 0;  //초기화
    
    for(var i=0;i < conv_array.length;i++){
        var item = conv_array[i];
        ctx.save();
        ctx.beginPath();
        ctx.moveTo(width/2, height/2);
        if(i == 0){
            ctx.arc(width/2, height/2, radius, (Math.PI/180)*0, (Math.PI/180)* item , false);
            degree = item;
            console.log(0, degree);
        } else {
            ctx.arc(width/2, height/2, radius, (Math.PI/180)*degree, (Math.PI/180)*(degree + item), false);
            console.log(degree, degree + item);
            degree =  degree + item;
        }
        ctx.closePath();
        ctx.stroke();
        ctx.restore();
    }
</script>
    

 

 

아참! 캔버스에서의 0도는 수평으로된 x좌표라고 생각하면된다.

예전시간에 보았던 사진이다..

 

 

따라서 위 소스코드에서 중심점을 270위치로 바꾸려면 소스코드를 아래처럼 수정해주어야 한다.

ctx.arc(width/2, height/2, radius, (Math.PI/180)*-90, (Math.PI/180)*(item-90), false);
degree = item-90;
console.log(0, degree);

 

전부 90도만큼 빼 주어야 중심점이 270으로 돌아가게 되는데..

만약 90도만큼 전부 빼 주게되면 나중에 추가적인 작업과 기능구현시에 생각해야될 부분이 많아지므로 해당 부분은 일단 넘어가도록 하자.

 

이번시간에는 원형 차트를 그리는 기초에 대해서 살펴 보았다.

다음시간에는 원형 차트의 이벤트부분에 대해서 살펴보도록 하자.

 

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글