이번시간에는 차트에 이벤트를 부여하는 방법이다.
맨 처음에 설명하였듯이 캔버스는 1개의 객체로 이루어져 있기 때문에 이벤트를 부여하는 방법은 데이터를 통해서 직접 계산식으로 구현해야 된다고 했었다.
앞선시간에 이벤트 부여하는 방법 3가지를 해 보았었다.
1. 사각형에 이벤트 부여 https://lts0606.tistory.com/284
2. 원에 이벤트 부여 https://lts0606.tistory.com/285
3. 다각형에 이벤트 부여 https://lts0606.tistory.com/286
여기서는 Bar 차트이므로 1번 사각형에 이벤트를 부여하는 방법을 적용해 보도록 하겠다.
캔버스에서의 위치는 캔버스가 html로부터 띄어진 높이와, html 좌측에서부터 멀어진 거리를 빼 주어야 위치값이 나온다고 하였다. * 기억이 안나면 사각형에 이벤트부여 방법을 다시보자.
그러면 지금껏 만들어진 코드에 매번 클릭이벤트를 주었으니 이번에는 마우스가 움직이는(mousemove)를 주어서 이벤트를 넣어보자.
기존 소스코드에 아래 소스코드를 추가하여보자.
canvas.addEventListener('mousemove', function (event) {
var x1 = event.clientX - canvas.offsetLeft; //캔버스가 html 좌측으로 떨어진 거리를 뺀다
var y1 = event.clientY - canvas.offsetTop; //캔버스가 html 위로부터 내려온 거리를 뺀다
console.log(x1, y1);
});
요렇게 추가하면 캔버스 위로 마우스가 움직일 때 마다 캔버스의 x좌표와 y좌표값을 나타내어 준다.
그러면 그려진 대상에 대해서 마우스가 내부에 들어왔다는 어떻게 판별하는 것 일까?
지금 모습은 사각형이 일정하게 간격을 가지고 그려진 상태이다.
넓이에 들어왔음을 판별하려면,
마우스가 움직일 때 마다 사각형을 그리는 시작점+비율 ~ 시작점+넓이 이내에 마우스가 올라오면 해당 그래프가 선택된 것이라 볼 수 있다.
높이에 들어왔음을 판별하려면,
사각형이 그려지는 시작점(비율) ~ 최대높이 이내에 마우스가 올라오면 마찬가지로 해당 그래프가 선택된 것이라 볼 수 있다.
위 높이, 넓이에 대한 조건이 동시에 만족하면 그래프가 선택된 것 이다.
이를 계산식으로 풀어내어보면, 사각형 이벤트 부여하기 방법에서 본 계산방법과 거의 비슷한 함수가 만들어지게 된다.
function isInsideRect(x1, y1){
var result = false;
var index = -1;
for(var i=0; i < value.length;i++){
var data = value[i];
var devide = i / value.length ;
var start_x = position.min_x + position.max_x*devide; //x 시작점은 최소값 + 비율
var end_x = start_x + wid; //x 종료점은 시작값 + 넓이
var start_y = position.max_y* ( 1-(data/100) ); //y시작점은 내부 사각형 그리기와 동일한 방법
var end_y = position.max_y ; //y종료점도 내부 사각형 그리기와 동일한 방법
if(x1 >= start_x && x1 <= end_x){
if(y1 >= start_y && y1 <= end_y){
result = true;
index = i;
break;
}
}
}
return {result:result, index:index};
}
해당 소스코드를 추가하여 실행하여보자.
사각형 영역에 들어올 때 마다 각각의 배열의 인덱스번호값을 가지고 결과가 나타나는 것을 볼 수 있다.
위 내용에 대한 전체 소스코드이다.
<!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 position = {
min_x : width * 0.1,
max_x : width * 0.9,
min_y : height * 0.1,
max_y : height * 0.9
}
var wid = 50;
var value = [90, 50, 60];
var virtualVal = value.slice().map((arg)=>1);
var adder = 0;
var interval = setInterval(() => {
ctx.clearRect(0, 0, width, height); //추가
virtualVal.forEach( (data, idx) => {
if(value[idx] > data){
var devide = idx / value.length ;
data++;
virtualVal[idx] = data;
ctx.strokeRect(position.min_x + position.max_x*devide, position.max_y* ( 1-(data/100) ), wid, position.max_y - position.max_y* ( 1-(data/100) ));
} else { //추가
var devide = idx / value.length ;
ctx.strokeRect(position.min_x + position.max_x*devide, position.max_y* ( 1-(data/100) ), wid, position.max_y - position.max_y* ( 1-(data/100) ));
}
});
var chekcer = virtualVal.slice().map((arg)=>false);
virtualVal.forEach( (data1, idx1) => {
value.forEach( (data2, idx2) => {
if(data1 >= data2 && idx1 == idx2){
chekcer[idx1] = true;
}
});
});
var breaker = true;
chekcer.forEach( arg => {
if(!arg){
breaker = false;
}
});
if(breaker){
console.log('fin');
clearInterval(interval);
makeText()
}
}, 10);
function makeText(){
value.forEach((data, idx) =>{
var devide = idx / value.length;
var len = (wid/2) - ctx.measureText(data+'').width / 2;
ctx.strokeText(data, position.min_x + position.max_x*devide + len, position.max_y + position.min_y/2);
});
}
canvas.addEventListener('mousemove', function (event) {
var x1 = event.clientX - canvas.offsetLeft;
var y1 = event.clientY - canvas.offsetTop;
var inn = isInsideRect(x1, y1);
if (inn.result) {
console.log(inn);
}
});
function isInsideRect(x1, y1){
var result = false;
var index = -1;
for(var i=0; i < value.length;i++){
var data = value[i];
var devide = i / value.length ;
var start_x = position.min_x + position.max_x*devide; //x 시작점은 최소값 + 비율
var end_x = start_x + wid; //x 종료점은 시작값 + 넓이
var start_y = position.max_y* ( 1-(data/100) ); //y시작점은 내부 사각형 그리기와 동일한 방법
var end_y = position.max_y ; //y종료점도 내부 사각형 그리기와 동일한 방법
if(x1 >= start_x && x1 <= end_x){
if(y1 >= start_y && y1 <= end_y){
result = true;
index = i;
break;
}
}
}
return {result:result, index:index};
}
</script>
이번시간에는 차트에 이벤트를 부여하는 방법에 대해서 살펴보았다.
다음시간에는 이벤트에 따른 색상변화에 대해서 살펴보도록 하겠다.
'Html 캔버스 > Html 캔버스 튜토리얼 (내가만든 차트!)' 카테고리의 다른 글
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 17 : 바 차트 5 (10) | 2020.02.20 |
---|---|
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 16 : 바 차트 4 (1) | 2020.02.19 |
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 14 : 바 차트 2 (0) | 2020.02.13 |
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 13 : 바 차트 1 (0) | 2020.02.12 |
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 12 : 이벤트 관리3 (6) | 2020.02.11 |
댓글