آموزش جامع Chart.js
کتابخانه نمودارهای تعاملی جاوااسکریپت — ۸ نوع نمودار، انیمیشن روان و بهروزرسانی زنده.
📦معرفی و نصب
Chart.js یکی از محبوبترین کتابخانههای جاوااسکریپت برای رسم نمودارهای تعاملی است. بر پایه <canvas> HTML5 کار میکند، بدون هیچ وابستگی خارجی.
نصب
<!-- فایل لوکال --> <script src="chart.umd.min.js"></script> <!-- CDN --> <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.2/dist/chart.umd.min.js"></script> /* NPM */ // npm install chart.js import { Chart } from 'chart.js/auto';
ساختار پایه
<!-- HTML: canvas --> <canvas id="myChart"></canvas> // JavaScript const chart = new Chart( document.getElementById('myChart'), { type: 'bar', // نوع نمودار data: { labels: [...], datasets: [{...}] }, options: { responsive: true, ... } } );
انواع نمودار
| نوع | مقدار type | کاربرد |
|---|---|---|
| خطی | line | روند زمانی، تغییرات متوالی |
| میلهای | bar | مقایسه دستهها |
| دایرهای | pie | نسبت بخشها از کل |
| دونات | doughnut | مثل pie + متن مرکزی |
| رادار | radar | مقایسه چند ویژگی |
| قطبی | polarArea | مقادیر با اندازه بصری |
| پراکنده | scatter | رابطه دو متغیر |
| حبابی | bubble | سه متغیر (x, y, r) |
{ type, data, options } یکسانی دارند. فقط با تغییر type، نوع نمودار عوض میشود بدون تغییر دادهها.
📈نمودار خطی type: 'line'
مناسب نمایش روند تغییرات در طول زمان: فروش ماهانه، بازدید سایت، دمای هوا.
new Chart(ctx, { type: 'line', data: { labels: ['فروردین', 'اردیبهشت', 'خرداد', 'تیر', 'مرداد', 'شهریور'], datasets: [{ label: 'فروش (میلیون)', data: [12, 19, 15, 25, 22, 30], borderColor: '#3498db', backgroundColor: 'rgba(52,152,219,0.15)', tension: 0.4, // انحنا: 0=خط مستقیم، 1=منحنی کامل fill: true, // پر کردن ناحیه زیر خط pointRadius: 5, borderWidth: 2.5, }] }, options: { responsive: true, plugins: { title: { display: true, text: 'آمار فروش ۶ ماهه' } }, scales: { y: { beginAtZero: true } } } });
Gradient Fill — پر کردن با گرادیان
// گرادیان از بالا به پایین const gradient = ctx.createLinearGradient(0, 0, 0, 400); gradient.addColorStop(0, 'rgba(52,152,219,0.6)'); // بالا: پررنگ gradient.addColorStop(1, 'rgba(52,152,219,0.0)'); // پایین: شفاف datasets[0].backgroundColor = gradient; // به جای رنگ ثابت
گزینههای مهم Dataset
| گزینه | توضیح |
|---|---|
tension | انحنای خط (0=مستقیم، 0.4=منحنی متوسط) |
fill | true=پر کردن ناحیه، false=خط ساده |
pointRadius | اندازه نقاط (0=پنهان) |
borderDash | خطچین: [5,5] |
stepped | true=پلهای (Step chart) |
spanGaps | پل زدن روی مقادیر null |
📊نمودار میلهای type: 'bar'
برای مقایسه مقادیر بین دستهها. با indexAxis: 'y' افقی میشود.
new Chart(ctx, { type: 'bar', data: { labels: ['Q1', 'Q2', 'Q3', 'Q4'], datasets: [ { label: 'محصول الف', data: [65, 59, 80, 81], backgroundColor: 'rgba(52,152,219,.8)', borderRadius: 4 }, { label: 'محصول ب', data: [28, 48, 40, 19], backgroundColor: 'rgba(231,76,60,.8)', borderRadius: 4 } ] }, options: { responsive: true, // indexAxis: 'y', ← برای نمودار افقی // scales: { x: { stacked: true }, y: { stacked: true } } ← انباشته } });
backgroundColor: ctx => ctx.parsed.y > 70 ? '#88ce02' : ctx.parsed.y > 40 ? '#3498db' : '#e74c3c'
🍏نمودار دایرهای و دونات pie / doughnut
برای نمایش نسبت و سهم هر بخش از کل. تفاوت doughnut فقط وجود سوراخ مرکزی است.
new Chart(ctx, { type: 'doughnut', // یا 'pie' data: { labels: ['موبایل', 'دسکتاپ', 'تبلت', 'سایر'], datasets: [{ data: [55, 28, 12, 5], backgroundColor: ['#3498db', '#e74c3c', '#f1c40f', '#95a5a6'], hoverOffset: 8 // بیرون آمدن هنگام hover }] }, options: { cutout: '60%', // اندازه سوراخ (0 = pie) plugins: { legend: { position: 'right' } } } });
Pie
Doughnut
🌐رادار و قطبی radar / polarArea
Radar: مقایسه چند موجودیت از نظر چند ویژگی (مثل مقایسه بازیکنان). Polar: شبیه دایرهای اما اندازه شعاع نشاندهنده مقدار است.
new Chart(ctx, { type: 'radar', data: { labels: ['سرعت', 'دقت', 'دریبل', 'دفاع', 'شوت', 'پاس'], datasets: [ { label: 'بازیکن الف', data: [85,92,78,60,88,90], backgroundColor: 'rgba(52,152,219,.3)', borderColor: '#3498db' }, { label: 'بازیکن ب', data: [72,80,95,75,70,85], backgroundColor: 'rgba(231,76,60,.3)', borderColor: '#e74c3c' } ] }, options: { scales: { r: { min: 0, max: 100, ticks: { stepSize: 20 } } } } });
Radar
Polar Area
💡Scatter و Bubble scatter / bubble
Scatter: نمایش رابطه بین دو متغیر (x و y). هر نقطه یک مشاهده است.
Bubble: مثل Scatter اما اندازه حباب (r) متغیر سومی را نشان میدهد.
Scatter Chart
new Chart(ctx, { type: 'scatter', data: { datasets: [{ label: 'گروه الف', data: [ { x: 10, y: 20 }, { x: 15, y: 32 }, { x: 22, y: 18 }, // ... ], backgroundColor: 'rgba(52,152,219,.7)', pointRadius: 6, pointHoverRadius: 9 }] }, options: { scales: { x: { type: 'linear', title: { display: true, text: 'محور X' } }, y: { type: 'linear', title: { display: true, text: 'محور Y' } } } } });
Bubble Chart
new Chart(ctx, { type: 'bubble', data: { datasets: [{ label: 'شهرها', data: [ { x: 10, y: 20, r: 15 }, // r = شعاع حباب { x: 25, y: 35, r: 8 }, { x: 40, y: 15, r: 22 } ], backgroundColor: 'rgba(136,206,2,.6)' }] } });
Scatter — دو گروه
Bubble — محبوبیت شهرها
labelsای ندارد. دادهها بهصورت {x, y} داده میشوند و محورها numeric هستند.
🎪نمودار ترکیبی (Mixed Chart)
در Chart.js میتوانید چند نوع نمودار را روی یک canvas ترکیب کنید — مثلاً میلهای برای مقادیر و خطی برای هدف یا میانگین.
new Chart(ctx, { type: 'bar', // نوع پیشفرض data: { labels: ['فروردین', 'اردیبهشت', 'خرداد', 'تیر'], datasets: [ { type: 'bar', // ← اضافه کردن type به هر dataset label: 'فروش واقعی', data: [65, 59, 80, 81], backgroundColor: 'rgba(52,152,219,.8)', borderRadius: 5, order: 2 // ترتیب رسم (بزرگتر = جلوتر) }, { type: 'line', // ← این dataset خطی رسم میشود label: 'هدف فروش', data: [70, 65, 75, 85], borderColor: '#e74c3c', borderDash: [6, 4], // خطچین pointStyle: 'circle', fill: false, tension: 0, order: 1 } ] } });
⚙تنظیمات و شخصیسازی
تنظیمات محورها (Scales)
options: {
scales: {
y: {
beginAtZero: true,
min: 0, max: 100,
title: { display: true, text: 'مقدار (٪)' },
grid: { color: 'rgba(0,0,0,.06)' },
ticks: {
callback: val => val + '٪', // فرمتبندی
stepSize: 20
}
},
x: { grid: { display: false } } // پنهان کردن خطوط عمودی
}
}
محور دوم Y (Dual Axis)
datasets: [
{ yAxisID: 'y', data: [...] }, // محور چپ
{ yAxisID: 'y1', data: [...] } // محور راست
],
scales: {
y: { type: 'linear', position: 'left' },
y1: { type: 'linear', position: 'right', grid: { drawOnChartArea: false } }
}
Tooltip سفارشی
plugins: {
tooltip: {
backgroundColor: 'rgba(44,52,59,.95)',
titleColor: '#88ce02',
bodyColor: '#fff',
padding: 12,
callbacks: {
label: ctx => ` ${ctx.parsed.y} میلیون تومان`,
footer: ctx => ctx[0].parsed.y > 70 ? '✅ هدف محقق شد' : '⚠️ زیر هدف'
}
}
}
انیمیشن
options: {
animation: {
duration: 1200,
easing: 'easeInOutQuart', // easeInQuad, easeOutBounce, easeInElastic ...
onComplete: () => console.log('آماده شد!')
}
}
📱بهروزرسانی زنده (Live Update)
با تغییر آرایه data و فراخوانی chart.update()، نمودار با انیمیشن بهروز میشود.
// اضافه کردن داده جدید chart.data.labels.push('مهر'); chart.data.datasets[0].data.push(42); // حذف داده قدیمی (rolling window) chart.data.labels.shift(); chart.data.datasets[0].data.shift(); chart.update(); // با انیمیشن chart.update('none'); // بدون انیمیشن (سریعتر)
chart.update('none') استفاده کنید تا انیمیشن اجرا نشود و CPU کمتر مصرف شود. تعداد نقاط را با shift() محدود نگه دارید.
👉Events و تعامل
Chart.js امکان دریافت رویداد کلیک، hover و انتخاب عناصر نمودار را فراهم میکند.
onClick روی نمودار
options: {
onClick: (event, elements) => {
if (elements.length > 0) {
const el = elements[0];
const datasetIndex = el.datasetIndex;
const dataIndex = el.index;
const label = chart.data.labels[dataIndex];
const value = chart.data.datasets[datasetIndex].data[dataIndex];
console.log(`کلیک: ${label} = ${value}`);
}
},
onHover: (event, elements) => {
event.native.target.style.cursor = elements.length ? 'pointer' : 'default';
}
}
getElementsAtEventForMode
// یافتن همه عناصر در یک point (بدون نیاز به onClick option) canvas.addEventListener('click', e => { const elements = chart.getElementsAtEventForMode( e, 'nearest', { intersect: true }, false ); if (elements.length) { const { datasetIndex, index } = elements[0]; console.log('کلیک شد:', chart.data.datasets[datasetIndex].data[index]); } });
برجستهسازی Dataset
// پنهان/نمایش یک dataset با کلیک document.getElementById('btn').addEventListener('click', () => { const meta = chart.getDatasetMeta(0); meta.hidden = !meta.hidden; chart.update(); });
🌟نکات حرفهای
متدهای مهم Chart
| متد | کاربرد |
|---|---|
chart.update() | اعمال تغییرات با انیمیشن |
chart.update('none') | اعمال بدون انیمیشن (سریعتر) |
chart.destroy() | حذف کامل و آزادسازی حافظه |
chart.reset() | اجرای مجدد انیمیشن ورود |
chart.resize() | تغییر اندازه دستی |
chart.toBase64Image() | خروجی تصویر PNG |
chart.getDatasetMeta(i) | اطلاعات Dataset شماره i |
دانلود نمودار به PNG
function downloadChart(chart, filename = 'chart') { const a = document.createElement('a'); a.download = filename + '.png'; a.href = chart.toBase64Image('image/png', 1.0); a.click(); }
بهترین روشها
- همیشه
chart.destroy()قبل از ساخت مجدد: جلوگیری از خطای "Canvas already in use" - از
responsive: trueاستفاده کنید — نمودار با resize پنجره سازگار میشود - برای live data از
update('none')استفاده کنید - داده را خارج از Chart نگه دارید — سپس update کنید
- تعداد نقاط را کنترل کنید — بیش از ۵۰۰ نقطه ممکن است کند شود
- پلاگین
chartjs-plugin-datalabels— نمایش مقادیر روی نمودار
🚀زمین بازی کد (Playground)
کد Chart.js را همینجا ویرایش کن و نمودار را زنده ببین. نوع نمودار، دادهها و رنگها را تغییر بده و ▶ اجرا را بزن. تب HTML شامل <canvas> است و تب JS کد نمودار. نسخهٔ ۴.۴.۲ آفلاین بارگذاری میشود.
type را به 'bar'، 'pie'، 'radar' و… تغییر دهی.