저번시간에는 이벤트를 부여하는 첫번째 방법으로 반지름 이내에 마우스가 들어온 경우에 대해서 감지하는 방법까지 알아 보았다.
이번시간에는 각 그려진 부채꼴 영역별로 감지된 도(degree)를 통해서 범위내에 들어온 경우에 대해서 살펴보도록 하겠다.
앞 시간 마지막 부분에서 아크탄젠트(탄젠트의 역함수)를 통해 중심점부터 마우스가 클릭한 곳 까지의 라디안 값을 구한뒤에 도(degree) 값으로 변환하였다.
해당 값을 보면 값이 -180 ~ 180 사이의 값이 나오게 되므로 이를 사용하기 쉽게 하려면 +180을 더해주면 된다.
그러면 0~ 360 값이 나오게 되므로 해당 값을 가지고 부채꼴 영역에 들어왔는지 판별하면 된다.
isInsideArc함수를 수정하여보자.
function isInsideArc(x1, y1){
var result1 = false;
var result2 = false;
var index = -1;
var circle_len = radius;
var x = width/2 - x1;
var y = height/2 - y1;
var my_len = Math.sqrt(Math.abs(x * x) + Math.abs(y * y)); //삼각함수
if(circle_len >= my_len){
result1 = true;
}
var rad = Math.atan2(y, x);
rad = (rad*180)/Math.PI; //음수가 나온다
rad += 180; //캔버스의 각도로 변경
if(result1){
event_array.forEach( (arr,idx) => { //각도 범위에 해당하는지 확인
if( rad >= arr[0] && rad <= arr[1]){
result2 = true;
index = idx;
}
});
}
return {result1:result1, result2:result2 ,index:index, degree : rad};
}
반지름에 들어온경우 event_array를 반복문을 통해서 해당 값이 범위에 있는지 확인하도록 변경 하였다.
event_array 값은 거의 맨 처음 시간에 했던 내용으로, 시작각과 종료각이 존재하는 배열이다.
그러면 해당코드를 수정한뒤에 실행시켜보자.
BAR 차트에서도 사용했던 방법처럼 마우스가 해당 조건에 모두 만족하면 도형을 변형시켜보도록 하자.
반지름 값을 키우면 도형의 크기가 커지고, 색깔을 변하게해서 시각적인 효과를 부여해보자.
이벤트 조건에 모두 만족한다면 그리는 방법은 처음 부채꼴을 그리는 방법과 거의 동일하게 하여주면 된다.
hoverCanvas라는 함수를 만들어보자.
function hoverCanvas(index){
ctx.clearRect(0,0,width, height); //지우기
for (var i = 0; i < conv_array.length; i++) { //다시그리기
var item = conv_array[i];
ctx.save();
ctx.beginPath();
var innRadius = radius;
ctx.moveTo(width / 2 , height / 2 );
if(index == i){ //대상이면 색칠 및 크기조정
ctx.lineWidth = 2;
ctx.strokeStyle='blue';
innRadius = radius * 1.1;
}
if (i == 0) {
ctx.arc(width / 2, height / 2, innRadius, (Math.PI / 180) * 0, (Math.PI / 180) * item, false);
degree = item; //초기화
} else {
ctx.arc(width / 2, height / 2, innRadius, (Math.PI / 180) * degree, (Math.PI / 180) * (degree + item), false);
degree = degree + item;
}
ctx.closePath();
ctx.stroke();
ctx.restore();
}
}
해당 함수를 addEventListener 부분에 추가하여주면 작업은 끝이났다.
아래는 최종 소스코드이다. * click이벤트를 mousemove로 바꾸었다.
<!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 = [100, 100, 100];
var degree = 360;
const radius = 50;
var sum = value.reduce((a, b) => a + b);
var conv_array = value.slice().map((data)=>{
var rate = data / sum;
var myDegree = degree * rate;
return myDegree;
});
degree = 0;
var event_array = value.slice().map( arg=> []);
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;
event_array[i] = [0, degree];
} else {
ctx.arc(width/2, height/2, radius, (Math.PI/180)*degree, (Math.PI/180)*(degree + item), false);
event_array[i] = [degree, degree+item];
degree = degree + item;
}
ctx.closePath();
ctx.stroke();
ctx.restore();
}
var drawed = false;
canvas.addEventListener('mousemove', function (event) {
var x1 = event.clientX - canvas.offsetLeft;
var y1 = event.clientY - canvas.offsetTop;
var inn = isInsideArc(x1, y1);
//console.log(inn);
if(inn.index > -1){
drawed = true;
hoverCanvas(inn.index);
} else {
if(drawed){
hoverCanvas(-1);
}
drawed = false;
}
});
function isInsideArc(x1, y1){
var result1 = false;
var result2 = false;
var index = -1;
var circle_len = radius;
var x = width/2 - x1;
var y = height/2 - y1;
var my_len = Math.sqrt(Math.abs(x * x) + Math.abs(y * y)); //삼각함수
if(circle_len >= my_len){
result1 = true;
}
var rad = Math.atan2(y, x);
rad = (rad*180)/Math.PI; //음수가 나온다
rad += 180; //캔버스의 각도로 변경
if(result1){
event_array.forEach( (arr,idx) => { //각도 범위에 해당하는지 확인
if( rad >= arr[0] && rad <= arr[1]){
result2 = true;
index = idx;
}
});
}
return {result1:result1, result2:result2 ,index:index, degree : rad};
}
function hoverCanvas(index){
ctx.clearRect(0,0,width, height); //지우기
for (var i = 0; i < conv_array.length; i++) { //다시그리기
var item = conv_array[i];
ctx.save();
ctx.beginPath();
var innRadius = radius;
ctx.moveTo(width / 2 , height / 2 );
if(index == i){ //대상이면 색칠 및 크기조정
ctx.lineWidth = 2;
ctx.strokeStyle='blue';
innRadius = radius * 1.1;
}
if (i == 0) {
ctx.arc(width / 2, height / 2, innRadius, (Math.PI / 180) * 0, (Math.PI / 180) * item, false);
degree = item; //초기화
} else {
ctx.arc(width / 2, height / 2, innRadius, (Math.PI / 180) * degree, (Math.PI / 180) * (degree + item), false);
degree = degree + item;
}
ctx.closePath();
ctx.stroke();
ctx.restore();
}
}
</script>
완성된 모습이다.
다음시간에는 차트 내부에 텍스트를 입히는 방법에 대해서 알아보도록 하겠다.
'Html 캔버스 > Html 캔버스 튜토리얼 (내가만든 차트!)' 카테고리의 다른 글
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 22 : 원 차트 5 (0) | 2020.02.24 |
---|---|
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 21 : 원 차트 4 (0) | 2020.02.24 |
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 19 : 원 차트 2 (2) | 2020.02.21 |
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 18 : 원 차트 1 (0) | 2020.02.20 |
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 17 : 바 차트 5 (10) | 2020.02.20 |
댓글