https://jobtc.tistory.com/146 (기본 차트)
https://jobtc.tistory.com/147 (실시간 차트)
https://jobtc.tistory.com/148 (서버 데이터 차트)
안녕하세요 IT여행자입니다.
두 번째 시간으로 이번에는 로컬에서 실시간으로 변경되는 데이터를 사용하여 그래프를 동적으로 그려서, 보다 생동감 있는 데이터 시각화를 해 보도록 하겠습니다.
주요 요점은 아래의 2가지입니다.
- line 그래프에서 꺾인 부분을 부드럽게 표현하기
- 실시간으로 데이터를 발생시켜 그래프에 적용하기
1. line 그래프에서 꺾인 부분을 부드럽게 표현하기
line 그래프에서 꺾인 부분을 부드럽게 표현하려면 tension 속성값을 지정하면 됩니다. tension은 곡률을 의미하는데, tension의 범위는 0~1까지입니다. 0으로 갈수록 직선이 되며, 1로 갈수록 곡선형으로 변경됩니다.
{
label: '판매',
data: data,
type : 'line',
borderWidth: 2, /* 선의 굵기 */
borderColor: '#00f',
pointBackgroundColor:colors, /* 포인트의 색상 */
pointRadius: 4, /* 포인트의 크기 */
tension : .35 /* 곡률 */
},
2. 실시간으로 그래프 그리기
데이터가 서버로부터 전달되는 것이 아니라 로컬에서 변경되는 상황이라 설정하고 그래프를 동적으로 그리도록 하겠습니다.
<button onclick="next()">next</button>
<button onclick="auto()">auto</button>
먼저 버튼 3개 만들고 각각 이전 데이터(prev), 다음 데이터(next), 실시간 변경데이터(auto) 형식으로 작업하도록 하겠습니다. prev 버튼과 next 버튼이 클릭되면 아래와 같은 함수가 호출됩니다.
var data=[44,22,66,44,88,55,77]
myChart.data.datasets[0].data = data;
myChart.data.datasets[1].data = data;
myChart.update();
}
var next = ()=>{
var data=[77,66,55,88,99,33,88]
myChart.data.datasets[0].data = data;
myChart.data.datasets[1].data = data;
myChart.update();
}
임의의 데이터를 data변수에 담은 뒤, myChart.data.datasets [0]과 myChart.data.datasets [1]은 화면에 그려진 첫 번째 그래프와 두 번째 그래프를 의미하며 이 객체의 data 속성에 동일한 데이터를 대입하여 같은 값을 갖는 그래프를 화면에 표시하였습니다. 그러나 전체 코드를 보면 알 수 있듯이 첫 번째 그래프는 막대그래프를 그리게 되고, 두 번째 그래프는 선 그래프를 그리게 됩니다.
auto 버튼을 클릭하면 약 20회에 걸쳐 렌덤 하게 발생한 데이터가 두 개의 그래프에 각각 적용되어 그래프의 모양은 다르지만 같은 값의 데이터가 화면에 출력됩니다.
let cnt=0;
while(cnt<20){
var data = [];
for(i=0; i<7; i++){
data.push(Math.random()*90+10);
}
myChart.data.datasets[0].data = data;
myChart.data.datasets[1].data = data;
myChart.update();
cnt++;
await new Promise(resolve => setTimeout(resolve, 1000)); /* 시간 지연 */
}
}
반복문 while을 다시 반복하기 전에 setTimeout() 함수를 사용하여 시간 지연 효과를 집어넣었습니다. new Promise()는 새로운 promise를 생성하는데 이를 해결하기 위해서는 resolve 콜백함수를 리턴 받아야 합니다. 따라서 setTimeout의 두 번째 인수값이 1000(1초)이 지나면 콜백 함수인 resolve를 실행하여 resolve를 리턴합니다. 이 resolve가 리턴될 때까지 기다리도록 하기 위해 new Promise() 앞에 await 명령을 추가하였습니다. 그런데 await 명령은 반드시 동기화 블록 내에서만 사용할 수 있기 때문에 해당 함수 블록의 시작 부분에 async명령을 사용하게 된 것입니다.
만약 이런 식으로 시간 지연이 일어나지 않으면 차트를 렌더링 하기도 전에 반복문이 모두 처리되고 말 것이기 때문에 정상적인 그래프를 볼 수 없게 됩니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="http://cdn.jsdelivr.net/npm/chart.js"></script>
<title>chart step 2</title>
<style>
#chart {
width: 600px;
height: 300px;
position: relative;
}
.btnZone {
display: flex;
justify-content: center;
}
</style>
</head>
<body>
<h3 class="info">
동적 챠트 그리기
</h3>
<div id="chart">
<canvas id="myChart"></canvas>
<div class="btnZone">
<button onclick="prev()">prev</button>
<button onclick="next()">next</button>
<button onclick="auto()">auto</button>
</div>
</div>
<script>
var ctx = document.querySelector('#myChart').getContext('2d')
var data = [10, 50, 30, 70, 90, 40, 55]
var x_labels = ['1월', '2월', '3월', '4월', '5월', '6월']
var colors = ['#f55a', '#5f5a', '#ff5a', '#f5fa', '#345a', '#123a', '#986a']
var myChart = new Chart(ctx, {
data: {
labels: x_labels, /*x축 라벨 */
datasets: [
{
label: '판매',
data: data,
type: 'line',
borderWidth: 2, /* 선의 굵기 */
borderColor: '#00f',
pointBackgroundColor: colors, /* 포인트의 색상 */
pointRadius: 4, /* 포인트의 크기 */
tension: .35 /* 곡률 */
},
{
label: '순이익',
data: data,
type: 'bar',
borderWidth: 0,
backgroundColor: colors,
},
]
},
options: {
responsive: true, /* 차크 크기 자동 조정 */
plugins: {
title: {
display: true,
text: '전체 판매현황',
}
},
scale: {
y: {
min: 0,
max: 110,
ticks: {
stepSize: 20,
}
}
}
}
})
var prev = () => {
var data = [44, 22, 66, 44, 88, 55, 77]
myChart.data.datasets[0].data = data;
myChart.data.datasets[1].data = data;
myChart.update();
}
var next = () => {
var data = [77, 66, 55, 88, 99, 33, 88]
myChart.data.datasets[0].data = data;
myChart.data.datasets[1].data = data;
myChart.update();
}
var auto = async () => {
let cnt = 0;
while (cnt < 20) {
var data = [];
for (i = 0; i < 7; i++) {
data.push(Math.random() * 90 + 10);
}
myChart.data.datasets[0].data = data;
myChart.data.datasets[1].data = data;
myChart.update();
cnt++;
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
</script>
</body>
</html>
auto 버튼이 클릭되면 차트의 모양이 20회 실시간으로 변화되는 것을 확인해 볼 수 있습니다.
'BOOKS > 수월한 자바스크립트' 카테고리의 다른 글
chart.js를 사용한 데이터 시각화하기 #3/3 (4) | 2024.12.27 |
---|---|
chart.js를 사용한 데이터 시각화하기 #1/3 (4) | 2024.12.26 |
개발 초보자를 위한 상위 Top10 구하기 (0) | 2023.02.24 |
초보 개발자를 위한 스무 고개 게임 만들기 (0) | 2023.02.20 |