레슨 5 / 8·20분
애니메이션과 인터랙션
애니메이션 설정
Chart.js는 차트가 처음 렌더링될 때와 데이터가 업데이트될 때 자동으로 애니메이션을 적용합니다. animation 옵션으로 지속 시간, 이징 함수, 콜백 등을 세밀하게 제어할 수 있습니다.
javascript
const chart = new Chart(ctx, {
type: 'bar',
data: { /* ... */ },
options: {
animation: {
duration: 2000,
easing: 'easeOutQuart',
// 애니메이션 완료 시 콜백
onComplete: function(animation) {
console.log('애니메이션 완료!');
},
// 각 프레임마다 호출
onProgress: function(animation) {
var progress = animation.currentStep / animation.numSteps;
console.log('진행률: ' + Math.round(progress * 100) + '%');
},
},
// 데이터셋별 애니메이션 설정
transitions: {
active: {
animation: { duration: 300 },
},
},
},
});이징 함수 종류
- •linear — 일정한 속도
- •easeInQuad — 느리게 시작
- •easeOutQuad — 느리게 끝남
- •easeInOutQuad — 느리게 시작하고 느리게 끝남
- •easeOutBounce — 바운스 효과
- •easeOutElastic — 탄성 효과
- •easeOutQuart — 부드럽게 감속 (추천)
- •easeInOutCubic — 자연스러운 시작과 끝
개별 속성 애니메이션
특정 속성에 대해서만 별도의 애니메이션을 적용할 수 있습니다. 예를 들어 x축은 빠르게, y축은 느리게 애니메이션하거나, 색상 변화에 별도 타이밍을 줄 수 있습니다.
javascript
options: {
animations: {
// Y축 값 애니메이션
y: {
duration: 1500,
easing: 'easeOutBounce',
from: function(ctx) {
// 초기 로드 시 아래에서 시작
if (ctx.type === 'data' && ctx.mode === 'default') {
return ctx.chart.scales.y.getPixelForValue(0);
}
},
},
// 색상 애니메이션
backgroundColor: {
duration: 500,
type: 'color',
from: 'rgba(0, 0, 0, 0)',
},
},
}툴팁 커스터마이징
javascript
options: {
plugins: {
tooltip: {
enabled: true,
mode: 'index', // 같은 X축 인덱스의 모든 데이터 표시
intersect: false, // 마우스가 정확히 포인트 위가 아니어도 표시
backgroundColor: 'rgba(0, 0, 0, 0.85)',
titleFont: { size: 15, weight: 'bold' },
bodyFont: { size: 13 },
padding: 12,
cornerRadius: 8,
displayColors: true, // 색상 박스 표시
// 제목 커스터마이징
callbacks: {
title: function(tooltipItems) {
return tooltipItems[0].label + ' 실적';
},
// 본문 커스터마이징
label: function(context) {
var label = context.dataset.label || '';
var value = context.parsed.y;
return label + ': ' + value.toLocaleString() + '원';
},
// 푸터 추가
footer: function(tooltipItems) {
var total = 0;
tooltipItems.forEach(function(item) {
total += item.parsed.y;
});
return '합계: ' + total.toLocaleString() + '원';
},
},
},
},
}클릭 이벤트와 데이터 인터랙션
javascript
// 차트 요소 클릭 이벤트
const chart = new Chart(ctx, {
type: 'bar',
data: { /* ... */ },
options: {
onClick: function(event, elements, chart) {
if (elements.length > 0) {
var element = elements[0];
var datasetIndex = element.datasetIndex;
var index = element.index;
var label = chart.data.labels[index];
var value = chart.data.datasets[datasetIndex].data[index];
console.log('클릭한 항목: ' + label + ', 값: ' + value);
// 클릭한 막대 강조 표시
var dataset = chart.data.datasets[datasetIndex];
var colors = dataset.backgroundColor.map(function(color, i) {
return i === index ? 'rgba(255, 99, 132, 0.8)' : 'rgba(54, 162, 235, 0.3)';
});
dataset.backgroundColor = colors;
chart.update();
}
},
onHover: function(event, elements) {
var target = event.native ? event.native.target : event.target;
target.style.cursor = elements.length > 0 ? 'pointer' : 'default';
},
},
});실시간 데이터 업데이트
javascript
// 실시간 데이터 추가
function addData(chart, label, data) {
chart.data.labels.push(label);
chart.data.datasets.forEach(function(dataset, i) {
dataset.data.push(data[i]);
});
// 최대 10개 데이터만 유지
if (chart.data.labels.length > 10) {
chart.data.labels.shift();
chart.data.datasets.forEach(function(dataset) {
dataset.data.shift();
});
}
chart.update('none'); // 애니메이션 없이 업데이트
}
// 2초마다 데이터 추가
setInterval(function() {
var now = new Date();
var label = now.getHours() + ':' + String(now.getMinutes()).padStart(2, '0');
var value = Math.floor(Math.random() * 100);
addData(chart, label, [value]);
}, 2000);💡
chart.update("none")을 호출하면 애니메이션 없이 즉시 차트를 갱신합니다. 실시간 데이터 스트리밍처럼 빈번한 업데이트에는 "none" 모드를 사용하여 성능을 최적화하세요.