앞전시간에는 도형을 그리고, 애니메이션을 주는 부분까지하여 단순한 차트의 형태를 구성하여 보았다.
이번에는 차트를 깔끔하게 그리는 방법과, 입력된 데이터가 하단에 표시되는 방법에 대해서 알아보겠다.
캔버스 내부에 차트를 그릴때 strokeRect함수를 사용해서 계속해서 그렸다.
그러다보니 내부에 줄이 그어진 상태로 차트가 완성되어서 되게 보기 불편한 모양이 되었다.
이러한 현상을 좀 해결하려면 가장 간단한 방법인 "지우고, 다시그리고" 방법을 써 주면 된다.
애니메이션을 주는 방법이 "지우고, 다시그리고" 방법이 짧은 시간동안 지속되면 마치 움직이는 효과를 나타내는 것 이라고 했으므로 처음 그리는 방법에서의 코드를 간단하게 수정하면 깔끔한 모양의 차트가 나오게 된다.
앞 시간 코드의 setInterval 부분을 수정해보도록 하자.
var interval = setInterval(() => {
ctx.clearRect(0, 0, width, height); //추가1
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 { //추가2
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);
}
}, 10);
"추가1" 에서의 캔버스는 지우는 효과를 실행하여 초기화를 하여준다.
"추가2" 에서 값이 변하지 않으면 기존 효과 그대로를 그리게 하였다.
수정된 코드를 실행하면 내부의 중첩된 선이 그려지는 것이 깔끔하게 해결된다.
지우고, 그리기를 반복하니 훨씬 깔금한 형태의 모양이 되었다.
물론 여기서는 stroke을 통해서 채우기 보다는 선긋기 모양을 표현하고 있으나 fill 형태로 채우기를 사용해도 상관 없다.
자, 다음으로 사용자가 입력한 데이터를 그려진 차트 아래에 표현하여보자.
기억을 더듬어 보면 텍스트를 그릴 때 사용하는 함수는 fillText 또는 strokeText를 통해서 실시 하였다.
마찬가지로 텍스트를 넣을 때도 그리는 방법을 이어서 하여주면된다.
그런데..텍스트를 굳이 여러번 그릴 필요가 없으니 애니메이션이 끝나는 부분에 넣어주도록 하자.
먼저 텍스트를 그릴 함수를 만든다.
function makeText(){
value.forEach((data, idx) =>{
var devide = idx / value.length ;
ctx.strokeText(data, position.min_x + position.max_x*devide, 100);
});
}
x좌표는 앞시간에 한 방법처럼 비율을 포함해서 간격을 주는 방법을 선택하였다.
해당 함수를 console.log('fin'); 이 존재하는 구간에 넣어주자.
이렇게 하고나면 텍스트가 높이는 100인 상태로 나타나게된다.
간격이 좀 애매하다.. 뭔가 중앙에 온 것 같지도 않고.
이를 수정하려면 앞시간에 살펴보았던 캔버스에서 제공한다는 텍스트의 길이를 그려주는 measureText 함수를 사용하면 쉽게 가능하다.
텍스트의 길이값 절반만큼 이동을 더 하도록 수정하여보자.
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, 100);
});
}
요걸 실행하면 아래 모습을 볼 수 있다.
텍스트를 저대로 두어도 상관 없지만 y좌표를 최댓값에서 최소값의 절반을 더해주면 텍스트가 하단부에 위치하게된다.
function makeText(){
value.forEach((data, idx) =>{
var devide = idx / value.length;
var len = (wid/2) - ctx.measureText(data+'').width / 2;
//최대높이 + 최소높이/2 만큼 텍스트를 아래로 가게 하였다.
ctx.strokeText(data, position.min_x + position.max_x*devide + len, position.max_y + position.min_y/2);
});
}
이렇게 하고나면 이제 좀 모양이 제법 그럴싸해진 차트가 완성이 된다.
최종 소스코드이다.
<!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 interval = setInterval(() => {
ctx.clearRect(0, 0, width, height); //추가1
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 { //추가2
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);
});
}
</script>
이번시간에는 차트를 좀 더 깔끔하게 수정하고 텍스트를 표현하여보았다.
다음시간에는 차트에 이벤트를 부여해보도록 하겠다.
'Html 캔버스 > Html 캔버스 튜토리얼 (내가만든 차트!)' 카테고리의 다른 글
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 16 : 바 차트 4 (1) | 2020.02.19 |
---|---|
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 15 : 바 차트 3 (0) | 2020.02.19 |
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 13 : 바 차트 1 (0) | 2020.02.12 |
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 12 : 이벤트 관리3 (6) | 2020.02.11 |
Html Canvas (Html 캔버스) 튜토리얼 (차트만들기!) - 11 : 이벤트 관리2 (0) | 2020.02.10 |
댓글