🎯 Exemples recommandés
Balanced sample collections from various categories for you to explore
Exemples Chart.js Library
Exemples complets de Chart.js incluant types de graphiques, options de personnalisation, animations et conceptions responsives
💻 Graphiques de Base Chart.js javascript
🟢 simple
⭐⭐
Graphiques essentiels Chart.js incluant histogrammes, lignes, secteurs et anneaux avec fonctionnalités interactives
⏱️ 20 min
🏷️ chartjs, charts, canvas
Prerequisites:
JavaScript, HTML, CSS, Chart.js library
// Chart.js Basic Charts Examples
// 1. Bar Chart
// HTML: <canvas id="barChart"></canvas>
function createBarChart() {
const ctx = document.getElementById('barChart').getContext('2d');
const data = {
labels: ['January', 'February', 'March', 'April', 'May', 'June'],
datasets: [{
label: 'Sales 2024',
data: [12, 19, 3, 5, 2, 3],
backgroundColor: [
'rgba(78, 121, 167, 0.8)',
'rgba(242, 142, 44, 0.8)',
'rgba(225, 87, 89, 0.8)',
'rgba(118, 183, 178, 0.8)',
'rgba(89, 161, 79, 0.8)',
'rgba(237, 201, 73, 0.8)'
],
borderColor: [
'rgba(78, 121, 167, 1)',
'rgba(242, 142, 44, 1)',
'rgba(225, 87, 89, 1)',
'rgba(118, 183, 178, 1)',
'rgba(89, 161, 79, 1)',
'rgba(237, 201, 73, 1)'
],
borderWidth: 2,
borderRadius: 5,
borderSkipped: false
}, {
label: 'Sales 2023',
data: [8, 15, 7, 9, 4, 6],
backgroundColor: 'rgba(175, 122, 161, 0.5)',
borderColor: 'rgba(175, 122, 161, 1)',
borderWidth: 2,
borderRadius: 5
}]
};
const config = {
type: 'bar',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
labels: {
padding: 20,
font: {
size: 14
}
}
},
title: {
display: true,
text: 'Monthly Sales Comparison',
font: {
size: 18,
weight: 'bold'
},
padding: {
bottom: 20
}
},
tooltip: {
backgroundColor: 'rgba(0, 0, 0, 0.8)',
titleFont: {
size: 14
},
bodyFont: {
size: 13
},
padding: 10,
cornerRadius: 4,
displayColors: true
}
},
scales: {
y: {
beginAtZero: true,
grid: {
color: 'rgba(0, 0, 0, 0.1)'
},
ticks: {
font: {
size: 12
}
},
title: {
display: true,
text: 'Sales (in thousands)',
font: {
size: 14,
weight: 'bold'
}
}
},
x: {
grid: {
display: false
},
ticks: {
font: {
size: 12
}
}
}
},
animation: {
duration: 1000,
easing: 'easeInOutQuart'
},
interaction: {
mode: 'index',
intersect: false
}
}
};
return new Chart(ctx, config);
}
// 2. Line Chart
// HTML: <canvas id="lineChart"></canvas>
function createLineChart() {
const ctx = document.getElementById('lineChart').getContext('2d');
const data = {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
datasets: [{
label: 'Revenue',
data: [30, 45, 42, 55, 48, 62, 58, 72, 68, 75, 80, 85],
borderColor: 'rgba(78, 121, 167, 1)',
backgroundColor: 'rgba(78, 121, 167, 0.1)',
borderWidth: 3,
pointRadius: 4,
pointHoverRadius: 6,
pointBackgroundColor: 'rgba(78, 121, 167, 1)',
pointBorderColor: '#fff',
pointBorderWidth: 2,
tension: 0.4,
fill: true
}, {
label: 'Expenses',
data: [20, 28, 35, 40, 32, 45, 42, 48, 52, 55, 58, 60],
borderColor: 'rgba(242, 142, 44, 1)',
backgroundColor: 'rgba(242, 142, 44, 0.1)',
borderWidth: 3,
pointRadius: 4,
pointHoverRadius: 6,
pointBackgroundColor: 'rgba(242, 142, 44, 1)',
pointBorderColor: '#fff',
pointBorderWidth: 2,
tension: 0.4,
fill: true
}]
};
const config = {
type: 'line',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
labels: {
padding: 20,
usePointStyle: true,
font: {
size: 14
}
}
},
title: {
display: true,
text: 'Financial Performance 2024',
font: {
size: 18,
weight: 'bold'
}
},
tooltip: {
mode: 'index',
intersect: false,
backgroundColor: 'rgba(0, 0, 0, 0.8)',
titleColor: '#fff',
bodyColor: '#fff',
borderColor: 'rgba(78, 121, 167, 1)',
borderWidth: 1
}
},
scales: {
y: {
beginAtZero: true,
grid: {
color: 'rgba(0, 0, 0, 0.1)'
},
ticks: {
font: {
size: 12
}
},
title: {
display: true,
text: 'Amount (in thousands)',
font: {
size: 14,
weight: 'bold'
}
}
},
x: {
grid: {
display: false
},
ticks: {
font: {
size: 12
}
}
}
},
interaction: {
mode: 'index',
intersect: false
},
animation: {
duration: 1500,
easing: 'easeInOutQuart'
},
elements: {
line: {
tension: 0.4
}
}
}
};
return new Chart(ctx, config);
}
// 3. Pie Chart
// HTML: <canvas id="pieChart"></canvas>
function createPieChart() {
const ctx = document.getElementById('pieChart').getContext('2d');
const data = {
labels: ['Electronics', 'Clothing', 'Food', 'Books', 'Sports', 'Other'],
datasets: [{
data: [25, 20, 18, 12, 15, 10],
backgroundColor: [
'rgba(78, 121, 167, 0.8)',
'rgba(242, 142, 44, 0.8)',
'rgba(225, 87, 89, 0.8)',
'rgba(118, 183, 178, 0.8)',
'rgba(89, 161, 79, 0.8)',
'rgba(237, 201, 73, 0.8)'
],
borderColor: '#fff',
borderWidth: 2,
hoverOffset: 10
}]
};
const config = {
type: 'pie',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'right',
labels: {
padding: 15,
usePointStyle: true,
font: {
size: 14
},
generateLabels: function(chart) {
const data = chart.data;
if (data.labels.length && data.datasets.length) {
return data.labels.map(function(label, i) {
const meta = chart.getDatasetMeta(0);
const total = meta.data.reduce((acc, val) => acc + val, 0);
const value = data.datasets[0].data[i];
const percentage = ((value / total) * 100).toFixed(1);
return {
text: `${label} (${percentage}%)`,
fillStyle: data.datasets[0].backgroundColor[i],
hidden: false,
index: i
};
});
}
return [];
}
}
},
title: {
display: true,
text: 'Sales by Category',
font: {
size: 18,
weight: 'bold'
}
},
tooltip: {
callbacks: {
label: function(context) {
const total = context.dataset.data.reduce((acc, val) => acc + val, 0);
const percentage = ((context.parsed / total) * 100).toFixed(1);
return `${context.label}: ${context.parsed} (${percentage}%)`;
}
}
}
},
animation: {
animateRotate: true,
animateScale: true,
duration: 1000,
easing: 'easeInOutQuart'
}
}
};
return new Chart(ctx, config);
}
// 4. Doughnut Chart
// HTML: <canvas id="doughnutChart"></canvas>
function createDoughnutChart() {
const ctx = document.getElementById('doughnutChart').getContext('2d');
const data = {
labels: ['Completed', 'In Progress', 'Pending', 'Cancelled'],
datasets: [{
data: [45, 25, 20, 10],
backgroundColor: [
'rgba(89, 161, 79, 0.8)',
'rgba(78, 121, 167, 0.8)',
'rgba(242, 142, 44, 0.8)',
'rgba(225, 87, 89, 0.8)'
],
borderColor: '#fff',
borderWidth: 2,
hoverOffset: 8
}]
};
const config = {
type: 'doughnut',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
cutout: '60%',
plugins: {
legend: {
position: 'bottom',
labels: {
padding: 20,
usePointStyle: true,
font: {
size: 14
}
}
},
title: {
display: true,
text: 'Project Status',
font: {
size: 18,
weight: 'bold'
}
},
tooltip: {
callbacks: {
label: function(context) {
const total = context.dataset.data.reduce((acc, val) => acc + val, 0);
const percentage = ((context.parsed / total) * 100).toFixed(1);
return `${context.label}: ${context.parsed} (${percentage}%)`;
}
}
}
},
animation: {
animateRotate: true,
animateScale: true,
duration: 1200,
easing: 'easeInOutQuart'
}
}
};
return new Chart(ctx, config);
}
// 5. Radar Chart
// HTML: <canvas id="radarChart"></canvas>
function createRadarChart() {
const ctx = document.getElementById('radarChart').getContext('2d');
const data = {
labels: ['Product Quality', 'Customer Service', 'Price', 'Delivery Speed', 'User Experience', 'Support'],
datasets: [{
label: 'Company A',
data: [85, 90, 70, 88, 92, 78],
borderColor: 'rgba(78, 121, 167, 1)',
backgroundColor: 'rgba(78, 121, 167, 0.2)',
borderWidth: 2,
pointBackgroundColor: 'rgba(78, 121, 167, 1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(78, 121, 167, 1)',
pointRadius: 4,
pointHoverRadius: 6
}, {
label: 'Company B',
data: [75, 85, 90, 70, 80, 88],
borderColor: 'rgba(242, 142, 44, 1)',
backgroundColor: 'rgba(242, 142, 44, 0.2)',
borderWidth: 2,
pointBackgroundColor: 'rgba(242, 142, 44, 1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(242, 142, 44, 1)',
pointRadius: 4,
pointHoverRadius: 6
}]
};
const config = {
type: 'radar',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'top',
labels: {
padding: 20,
usePointStyle: true,
font: {
size: 14
}
}
},
title: {
display: true,
text: 'Company Comparison',
font: {
size: 18,
weight: 'bold'
}
}
},
scales: {
r: {
beginAtZero: true,
max: 100,
ticks: {
stepSize: 20,
font: {
size: 12
}
},
grid: {
color: 'rgba(0, 0, 0, 0.1)'
},
pointLabels: {
font: {
size: 13,
weight: 'bold'
}
}
}
},
animation: {
duration: 1000,
easing: 'easeInOutQuart'
},
elements: {
line: {
borderWidth: 2
}
}
}
};
return new Chart(ctx, config);
}
// Initialize all charts
document.addEventListener('DOMContentLoaded', function() {
// Set default chart styles
Chart.defaults.font.family = 'Arial, sans-serif';
Chart.defaults.color = '#333';
// Create charts
const barChart = createBarChart();
const lineChart = createLineChart();
const pieChart = createPieChart();
const doughnutChart = createDoughnutChart();
const radarChart = createRadarChart();
// Store chart instances for later reference
window.charts = {
bar: barChart,
line: lineChart,
pie: pieChart,
doughnut: doughnutChart,
radar: radarChart
};
});
💻 Personnalisation Avancée Chart.js javascript
🟡 intermediate
⭐⭐⭐
Fonctionnalités avancées Chart.js incluant graphiques mixtes, plugins personnalisés, animations et conceptions responsives
⏱️ 35 min
🏷️ chartjs, advanced, plugins, real-time
Prerequisites:
Advanced JavaScript, Chart.js, Canvas API, CSS animations
// Chart.js Advanced Customization Examples
// 1. Mixed Chart (Bar + Line)
// HTML: <canvas id="mixedChart"></canvas>
function createMixedChart() {
const ctx = document.getElementById('mixedChart').getContext('2d');
const data = {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
datasets: [{
type: 'bar',
label: 'Revenue',
data: [12000, 19000, 15000, 25000, 22000, 30000, 28000, 35000, 32000, 38000, 42000, 45000],
backgroundColor: 'rgba(78, 121, 167, 0.8)',
borderColor: 'rgba(78, 121, 167, 1)',
borderWidth: 2,
borderRadius: 5,
yAxisID: 'y'
}, {
type: 'line',
label: 'Growth Rate %',
data: [10, 15, 8, 25, 18, 30, 22, 35, 28, 32, 38, 40],
borderColor: 'rgba(242, 142, 44, 1)',
backgroundColor: 'rgba(242, 142, 44, 0.1)',
borderWidth: 3,
pointRadius: 5,
pointHoverRadius: 7,
tension: 0.4,
yAxisID: 'y1',
fill: true
}]
};
const config = {
type: 'bar', // Base type
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
interaction: {
mode: 'index',
intersect: false
},
plugins: {
title: {
display: true,
text: 'Revenue vs Growth Rate',
font: {
size: 18,
weight: 'bold'
}
},
legend: {
position: 'top',
labels: {
usePointStyle: true,
padding: 20
}
},
tooltip: {
mode: 'index',
intersect: false,
backgroundColor: 'rgba(0, 0, 0, 0.8)',
titleColor: '#fff',
bodyColor: '#fff',
borderColor: 'rgba(78, 121, 167, 1)',
borderWidth: 1
}
},
scales: {
y: {
type: 'linear',
display: true,
position: 'left',
title: {
display: true,
text: 'Revenue ($)',
font: {
weight: 'bold'
}
},
grid: {
color: 'rgba(0, 0, 0, 0.1)'
}
},
y1: {
type: 'linear',
display: true,
position: 'right',
title: {
display: true,
text: 'Growth Rate (%)',
font: {
weight: 'bold'
}
},
grid: {
drawOnChartArea: false
}
},
x: {
grid: {
display: false
}
}
},
animation: {
duration: 2000,
easing: 'easeInOutQuart'
}
}
};
return new Chart(ctx, config);
}
// 2. Bubble Chart
// HTML: <canvas id="bubbleChart"></canvas>
function createBubbleChart() {
const ctx = document.getElementById('bubbleChart').getContext('2d');
const data = {
datasets: [{
label: 'Technology Companies',
data: [
{ x: 20, y: 30, r: 15, company: 'Apple', marketCap: 2000 },
{ x: 40, y: 45, r: 25, company: 'Microsoft', marketCap: 1800 },
{ x: 30, y: 25, r: 20, company: 'Google', marketCap: 1600 },
{ x: 35, y: 35, r: 18, company: 'Amazon', marketCap: 1500 },
{ x: 25, y: 40, r: 12, company: 'Meta', marketCap: 800 },
{ x: 45, y: 50, r: 10, company: 'Tesla', marketCap: 700 }
],
backgroundColor: [
'rgba(78, 121, 167, 0.6)',
'rgba(242, 142, 44, 0.6)',
'rgba(225, 87, 89, 0.6)',
'rgba(118, 183, 178, 0.6)',
'rgba(89, 161, 79, 0.6)',
'rgba(237, 201, 73, 0.6)'
],
borderColor: [
'rgba(78, 121, 167, 1)',
'rgba(242, 142, 44, 1)',
'rgba(225, 87, 89, 1)',
'rgba(118, 183, 178, 1)',
'rgba(89, 161, 79, 1)',
'rgba(237, 201, 73, 1)'
],
borderWidth: 2
}, {
label: 'Banks',
data: [
{ x: 50, y: 20, r: 20, company: 'JP Morgan', marketCap: 450 },
{ x: 55, y: 25, r: 18, company: 'Bank of America', marketCap: 280 },
{ x: 48, y: 15, r: 15, company: 'Wells Fargo', marketCap: 220 },
{ x: 52, y: 30, r: 14, company: 'Citigroup', marketCap: 180 }
],
backgroundColor: 'rgba(175, 122, 161, 0.6)',
borderColor: 'rgba(175, 122, 161, 1)',
borderWidth: 2
}]
};
const config = {
type: 'bubble',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: 'Company Analysis',
font: {
size: 18,
weight: 'bold'
}
},
legend: {
position: 'top'
},
tooltip: {
callbacks: {
label: function(context) {
const item = context.raw;
return [
`${item.company}`,
`Revenue Growth: ${item.x}%`,
`Profit Margin: ${item.y}%`,
`Market Cap: $${item.marketCap}B`,
`Employees: ${item.r}K`
];
}
}
}
},
scales: {
x: {
title: {
display: true,
text: 'Revenue Growth (%)',
font: {
weight: 'bold'
}
},
min: 0,
max: 60
},
y: {
title: {
display: true,
text: 'Profit Margin (%)',
font: {
weight: 'bold'
}
},
min: 0,
max: 60
}
},
animation: {
duration: 1500,
easing: 'easeInOutQuart'
}
}
};
return new Chart(ctx, config);
}
// 3. Custom Plugin Example - Trend Line
// HTML: <canvas id="trendChart"></canvas>
function createTrendChart() {
// Custom plugin to draw trend line
const trendLinePlugin = {
id: 'trendLine',
beforeDraw: (chart) => {
const ctx = chart.ctx;
const xAxis = chart.scales.x;
const yAxis = chart.scales.y;
const dataset = chart.data.datasets[0];
const data = dataset.data;
// Calculate linear regression
const n = data.length;
const sumX = data.reduce((sum, point, index) => sum + index, 0);
const sumY = data.reduce((sum, point) => sum + point, 0);
const sumXY = data.reduce((sum, point, index) => sum + index * point, 0);
const sumX2 = data.reduce((sum, point, index) => sum + index * index, 0);
const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
const intercept = (sumY - slope * sumX) / n;
// Draw trend line
ctx.save();
ctx.beginPath();
ctx.strokeStyle = 'rgba(242, 142, 44, 0.8)';
ctx.lineWidth = 2;
ctx.setLineDash([5, 5]);
const startX = xAxis.getPixelForValue(0);
const startY = yAxis.getPixelForValue(intercept);
const endX = xAxis.getPixelForValue(n - 1);
const endY = yAxis.getPixelForValue(slope * (n - 1) + intercept);
ctx.moveTo(startX, startY);
ctx.lineTo(endX, endY);
ctx.stroke();
// Add trend line label
ctx.setLineDash([]);
ctx.fillStyle = 'rgba(242, 142, 44, 1)';
ctx.font = '14px Arial';
ctx.fillText('Trend Line', endX - 50, endY - 10);
ctx.restore();
}
};
const ctx = document.getElementById('trendChart').getContext('2d');
const data = {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
datasets: [{
label: 'Sales',
data: [30, 45, 42, 55, 48, 62, 58, 72, 68, 75, 80, 85],
borderColor: 'rgba(78, 121, 167, 1)',
backgroundColor: 'rgba(78, 121, 167, 0.1)',
borderWidth: 3,
tension: 0.4,
fill: true
}]
};
const config = {
type: 'line',
data: data,
plugins: [trendLinePlugin],
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
title: {
display: true,
text: 'Sales with Trend Analysis',
font: {
size: 18,
weight: 'bold'
}
},
legend: {
display: true,
position: 'top'
}
},
scales: {
y: {
beginAtZero: true
}
},
animation: {
duration: 2000,
easing: 'easeInOutQuart'
}
}
};
return new Chart(ctx, config);
}
// 4. Real-time Chart
// HTML: <canvas id="realtimeChart"></canvas>
function createRealtimeChart() {
const ctx = document.getElementById('realtimeChart').getContext('2d');
const initialData = Array.from({ length: 20 }, () => Math.random() * 100);
const labels = Array.from({ length: 20 }, (_, i) => `T-${i}`);
const data = {
labels: labels,
datasets: [{
label: 'CPU Usage (%)',
data: initialData,
borderColor: 'rgba(78, 121, 167, 1)',
backgroundColor: 'rgba(78, 121, 167, 0.1)',
borderWidth: 2,
tension: 0.4,
fill: true
}, {
label: 'Memory Usage (%)',
data: initialData.map(() => Math.random() * 100),
borderColor: 'rgba(242, 142, 44, 1)',
backgroundColor: 'rgba(242, 142, 44, 0.1)',
borderWidth: 2,
tension: 0.4,
fill: true
}]
};
const config = {
type: 'line',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 0 // Disable animation for real-time updates
},
plugins: {
title: {
display: true,
text: 'Real-time System Monitoring',
font: {
size: 18,
weight: 'bold'
}
},
legend: {
display: true,
position: 'top'
}
},
scales: {
y: {
beginAtZero: true,
max: 100,
title: {
display: true,
text: 'Usage (%)',
font: {
weight: 'bold'
}
}
},
x: {
title: {
display: true,
text: 'Time',
font: {
weight: 'bold'
}
}
}
},
interaction: {
mode: 'index',
intersect: false
}
}
};
const chart = new Chart(ctx, config);
// Update chart with real-time data
setInterval(() => {
chart.data.datasets[0].data.push(Math.random() * 100);
chart.data.datasets[0].data.shift();
chart.data.datasets[1].data.push(Math.random() * 100);
chart.data.datasets[1].data.shift();
chart.data.labels.push(`T-${Date.now() % 100}`);
chart.data.labels.shift();
chart.update('none'); // Update without animation
}, 1000);
return chart;
}
// 5. Responsive Chart Configuration
function createResponsiveCharts() {
// Common responsive options
const responsiveOptions = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
labels: {
boxWidth: 15,
padding: 20,
font: {
size: 12
}
}
},
tooltip: {
titleFont: {
size: 14
},
bodyFont: {
size: 12
},
padding: 10,
cornerRadius: 4
}
}
};
// Font size adjustments based on screen size
const getFontSize = (baseSize) => {
return window.innerWidth < 768 ? baseSize * 0.8 : baseSize;
};
// Apply responsive configuration
Chart.defaults.font.family = 'Arial, sans-serif';
Chart.defaults.font.size = getFontSize(12);
return responsiveOptions;
}
// 6. Custom Animation Example
function createAnimatedChart() {
const ctx = document.getElementById('animatedChart').getContext('2d');
const data = {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
datasets: [{
label: 'Monthly Sales',
data: [0, 0, 0, 0, 0, 0], // Start with zeros
backgroundColor: 'rgba(78, 121, 167, 0.8)',
borderColor: 'rgba(78, 121, 167, 1)',
borderWidth: 2,
borderRadius: 5
}]
};
const config = {
type: 'bar',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
animation: {
onComplete: () => {
console.log('Animation completed!');
},
delay: (context) => {
let delay = 0;
if (context.type === 'data' && context.mode === 'default') {
delay = context.dataIndex * 200 + context.datasetIndex * 100;
}
return delay;
},
duration: 1000,
easing: 'easeInOutQuart'
},
plugins: {
title: {
display: true,
text: 'Animated Bar Chart',
font: {
size: 18,
weight: 'bold'
}
}
}
}
};
const chart = new Chart(ctx, config);
// Animate data after a delay
setTimeout(() => {
chart.data.datasets[0].data = [65, 59, 80, 81, 56, 55];
chart.update();
}, 500);
return chart;
}
// Initialize all advanced charts
document.addEventListener('DOMContentLoaded', function() {
// Apply responsive configuration
createResponsiveCharts();
// Create advanced charts
const mixedChart = createMixedChart();
const bubbleChart = createBubbleChart();
const trendChart = createTrendChart();
const realtimeChart = createRealtimeChart();
const animatedChart = createAnimatedChart();
// Store chart instances
window.advancedCharts = {
mixed: mixedChart,
bubble: bubbleChart,
trend: trendChart,
realtime: realtimeChart,
animated: animatedChart
};
});
💻 Tableau de Bord Interactif Chart.js javascript
🔴 complex
⭐⭐⭐⭐
Tableau de bord complet avec plusieurs graphiques, mises à jour en temps réel, filtres et synchronisation de données
⏱️ 60 min
🏷️ chartjs, dashboard, real-time, interactive
Prerequisites:
Advanced JavaScript, Chart.js, CSS Grid/Flexbox, Data visualization concepts
// Chart.js Interactive Dashboard with Real-time Updates
// Dashboard configuration and data management
class ChartDashboard {
constructor(containerId) {
this.container = document.getElementById(containerId);
this.charts = {};
this.filters = {
dateRange: 'month',
category: 'all',
region: 'all'
};
this.realTimeData = [];
this.updateInterval = null;
this.init();
}
init() {
this.createLayout();
this.createControls();
this.createCharts();
this.setupEventListeners();
this.startRealTimeUpdates();
}
createLayout() {
// Main dashboard container
this.container.innerHTML = `
<div class="dashboard-header">
<h1>Sales Analytics Dashboard</h1>
<div class="header-stats">
<div class="stat-card">
<h3>Total Revenue</h3>
<span class="stat-value" id="totalRevenue">$0</span>
</div>
<div class="stat-card">
<h3>Total Orders</h3>
<span class="stat-value" id="totalOrders">0</span>
</div>
<div class="stat-card">
<h3>Average Order Value</h3>
<span class="stat-value" id="avgOrderValue">$0</span>
</div>
<div class="stat-card">
<h3>Conversion Rate</h3>
<span class="stat-value" id="conversionRate">0%</span>
</div>
</div>
</div>
<div class="dashboard-filters">
<select id="dateRange" class="filter-select">
<option value="week">Last Week</option>
<option value="month" selected>Last Month</option>
<option value="quarter">Last Quarter</option>
<option value="year">Last Year</option>
</select>
<select id="category" class="filter-select">
<option value="all">All Categories</option>
<option value="electronics">Electronics</option>
<option value="clothing">Clothing</option>
<option value="food">Food</option>
<option value="books">Books</option>
</select>
<select id="region" class="filter-select">
<option value="all">All Regions</option>
<option value="north">North</option>
<option value="south">South</option>
<option value="east">East</option>
<option value="west">West</option>
</select>
<button id="exportBtn" class="export-btn">Export Data</button>
</div>
<div class="dashboard-content">
<div class="chart-container">
<h3>Revenue Trend</h3>
<canvas id="revenueChart"></canvas>
</div>
<div class="chart-container">
<h3>Category Distribution</h3>
<canvas id="categoryChart"></canvas>
</div>
<div class="chart-container">
<h3>Regional Performance</h3>
<canvas id="regionalChart"></canvas>
</div>
<div class="chart-container">
<h3>Real-time Metrics</h3>
<canvas id="realtimeChart"></canvas>
</div>
</div>
`;
// Add CSS styles
const style = document.createElement('style');
style.textContent = `
.dashboard {
font-family: 'Arial', sans-serif;
padding: 20px;
background: #f8f9fa;
}
.dashboard-header {
margin-bottom: 30px;
text-align: center;
}
.dashboard-header h1 {
color: #333;
margin: 0 0 20px 0;
}
.header-stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-bottom: 20px;
}
.stat-card {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
text-align: center;
}
.stat-card h3 {
color: #666;
margin: 0 0 10px 0;
font-size: 14px;
}
.stat-value {
font-size: 24px;
font-weight: bold;
color: #4e79a7;
}
.dashboard-filters {
display: flex;
gap: 15px;
margin-bottom: 30px;
flex-wrap: wrap;
align-items: center;
padding: 20px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.filter-select {
padding: 10px 15px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.export-btn {
padding: 10px 20px;
background: #4e79a7;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.export-btn:hover {
background: #3a5a8c;
}
.dashboard-content {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
gap: 20px;
}
.chart-container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.chart-container h3 {
margin: 0 0 20px 0;
color: #333;
}
canvas {
max-height: 300px;
}
@media (max-width: 768px) {
.header-stats {
grid-template-columns: repeat(2, 1fr);
}
.dashboard-content {
grid-template-columns: 1fr;
}
}
`;
document.head.appendChild(style);
}
createControls() {
// Export functionality
document.getElementById('exportBtn').addEventListener('click', () => {
this.exportData();
});
}
createCharts() {
// Revenue trend chart
this.charts.revenue = this.createRevenueChart();
// Category distribution chart
this.charts.category = this.createCategoryChart();
// Regional performance chart
this.charts.regional = this.createRegionalChart();
// Real-time metrics chart
this.charts.realtime = this.createRealtimeChart();
}
createRevenueChart() {
const ctx = document.getElementById('revenueChart').getContext('2d');
const data = this.generateRevenueData();
return new Chart(ctx, {
type: 'line',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: true,
position: 'top'
}
},
scales: {
y: {
beginAtZero: true,
title: {
display: true,
text: 'Revenue ($)'
}
}
},
interaction: {
mode: 'index',
intersect: false
},
animation: {
duration: 1000
}
}
});
}
createCategoryChart() {
const ctx = document.getElementById('categoryChart').getContext('2d');
const data = this.generateCategoryData();
return new Chart(ctx, {
type: 'doughnut',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'bottom'
},
tooltip: {
callbacks: {
label: function(context) {
const total = context.dataset.data.reduce((a, b) => a + b, 0);
const percentage = ((context.parsed / total) * 100).toFixed(1);
return `${context.label}: ${percentage}%`;
}
}
}
},
animation: {
animateRotate: true,
animateScale: true,
duration: 1000
}
}
});
}
createRegionalChart() {
const ctx = document.getElementById('regionalChart').getContext('2d');
const data = this.generateRegionalData();
return new Chart(ctx, {
type: 'bar',
data: data,
options: {
responsive: true,
maintainAspectRatio: false,
indexAxis: 'y',
plugins: {
legend: {
display: false
}
},
scales: {
x: {
beginAtZero: true,
title: {
display: true,
text: 'Revenue ($)'
}
}
},
animation: {
duration: 1000
}
}
});
}
createRealtimeChart() {
const ctx = document.getElementById('realtimeChart').getContext('2d');
const initialData = this.generateRealtimeData();
return new Chart(ctx, {
type: 'line',
data: initialData,
options: {
responsive: true,
maintainAspectRatio: false,
animation: {
duration: 0 // Disable animations for real-time updates
},
scales: {
y: {
beginAtZero: true,
max: 100
}
},
plugins: {
legend: {
display: true,
position: 'top'
}
}
}
});
}
generateRevenueData() {
const labels = this.getDateLabels();
const datasets = [{
label: 'Revenue',
data: labels.map(() => Math.random() * 50000 + 10000),
borderColor: '#4e79a7',
backgroundColor: 'rgba(78, 121, 167, 0.1)',
borderWidth: 2,
tension: 0.4,
fill: true
}, {
label: 'Target',
data: labels.map(() => 40000),
borderColor: '#f28e2c',
backgroundColor: 'rgba(242, 142, 44, 0.1)',
borderWidth: 2,
borderDash: [5, 5],
tension: 0,
fill: false
}];
return { labels, datasets };
}
generateCategoryData() {
const categories = ['Electronics', 'Clothing', 'Food', 'Books', 'Other'];
const data = categories.map(() => Math.random() * 10000 + 5000);
return {
labels: categories,
datasets: [{
data: data,
backgroundColor: [
'#4e79a7',
'#f28e2c',
'#e15759',
'#76b7b2',
'#59a14f'
],
borderWidth: 2,
borderColor: '#fff'
}]
};
}
generateRegionalData() {
const regions = ['North', 'South', 'East', 'West'];
const datasets = [{
label: 'This Month',
data: regions.map(() => Math.random() * 50000 + 10000),
backgroundColor: '#4e79a7'
}, {
label: 'Last Month',
data: regions.map(() => Math.random() * 50000 + 10000),
backgroundColor: '#76b7b2'
}];
return {
labels: regions,
datasets: datasets
};
}
generateRealtimeData() {
const labels = Array.from({ length: 20 }, (_, i) => `${i}s ago`);
const datasets = [{
label: 'Active Users',
data: Array.from({ length: 20 }, () => Math.random() * 100 + 50),
borderColor: '#e15759',
backgroundColor: 'rgba(225, 87, 89, 0.1)',
borderWidth: 2,
tension: 0.4,
fill: true
}, {
label: 'Server Load',
data: Array.from({ length: 20 }, () => Math.random() * 100),
borderColor: '#59a14f',
backgroundColor: 'rgba(89, 161, 79, 0.1)',
borderWidth: 2,
tension: 0.4,
fill: true
}];
return { labels, datasets };
}
getDateLabels() {
const dateRange = this.filters.dateRange;
const count = this.getDateRangeCount(dateRange);
const labels = [];
for (let i = count - 1; i >= 0; i--) {
const date = new Date();
switch (dateRange) {
case 'week':
date.setDate(date.getDate() - i);
labels.push(date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }));
break;
case 'month':
date.setDate(date.getDate() - i);
labels.push(date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }));
break;
case 'quarter':
date.setDate(date.getDate() - (i * 7));
labels.push(date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' }));
break;
case 'year':
date.setMonth(date.getMonth() - i);
labels.push(date.toLocaleDateString('en-US', { month: 'short' }));
break;
}
}
return labels;
}
getDateRangeCount(dateRange) {
switch (dateRange) {
case 'week': return 7;
case 'month': return 30;
case 'quarter': return 13;
case 'year': return 12;
default: return 30;
}
}
setupEventListeners() {
// Date range filter
document.getElementById('dateRange').addEventListener('change', (e) => {
this.filters.dateRange = e.target.value;
this.updateCharts();
});
// Category filter
document.getElementById('category').addEventListener('change', (e) => {
this.filters.category = e.target.value;
this.updateCharts();
});
// Region filter
document.getElementById('region').addEventListener('change', (e) => {
this.filters.region = e.target.value;
this.updateCharts();
});
// Window resize handler
window.addEventListener('resize', () => {
Object.values(this.charts).forEach(chart => {
chart.resize();
});
});
}
updateCharts() {
// Update revenue chart
const revenueData = this.generateRevenueData();
this.charts.revenue.data = revenueData;
this.charts.revenue.update();
// Update category chart
const categoryData = this.generateCategoryData();
this.charts.category.data = categoryData;
this.charts.category.update();
// Update regional chart
const regionalData = this.generateRegionalData();
this.charts.regional.data = regionalData;
this.charts.regional.update();
// Update KPIs
this.updateKPIs();
}
updateKPIs() {
const revenue = Math.random() * 1000000 + 500000;
const orders = Math.floor(Math.random() * 10000 + 5000);
const avgOrder = revenue / orders;
const conversionRate = Math.random() * 10 + 2;
document.getElementById('totalRevenue').textContent = `$${revenue.toFixed(0).replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`;
document.getElementById('totalOrders').textContent = orders.toLocaleString();
document.getElementById('avgOrderValue').textContent = `$${avgOrder.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`;
document.getElementById('conversionRate').textContent = `${conversionRate.toFixed(1)}%`;
}
startRealTimeUpdates() {
this.updateInterval = setInterval(() => {
this.updateRealtimeChart();
}, 2000);
}
updateRealtimeChart() {
const chart = this.charts.realtime;
// Shift data
chart.data.labels.shift();
chart.data.labels.push('Now');
chart.data.datasets.forEach(dataset => {
dataset.data.shift();
dataset.data.push(Math.random() * 100 + 50);
});
chart.update('none'); // Update without animation
}
exportData() {
const data = {
dateRange: this.filters.dateRange,
category: this.filters.category,
region: this.filters.region,
timestamp: new Date().toISOString(),
charts: {
revenue: this.charts.revenue.data,
category: this.charts.category.data,
regional: this.charts.regional.data,
realtime: this.charts.realtime.data
}
};
// Create CSV
const csv = this.convertToCSV(data);
// Download CSV
const blob = new Blob([csv], { type: 'text/csv' });
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `dashboard-export-${Date.now()}.csv`;
a.click();
window.URL.revokeObjectURL(url);
}
convertToCSV(data) {
let csv = 'Dashboard Export\n';
csv += `Export Date: ${data.timestamp}\n\n`;
// Add filters
csv += 'Filters:\n';
csv += `Date Range: ${data.dateRange}\n`;
csv += `Category: ${data.category}\n`;
csv += `Region: ${data.region}\n\n`;
// Add chart data
Object.entries(data.charts).forEach(([chartName, chartData]) => {
csv += `${chartName.toUpperCase()} Data:\n`;
if (chartData.labels) {
csv += 'Labels,' + chartData.labels.join(',') + '\n';
}
if (chartData.datasets) {
chartData.datasets.forEach((dataset, index) => {
csv += `${dataset.label || `Dataset ${index}`},`;
csv += dataset.data.join(',') + '\n';
});
}
csv += '\n';
});
return csv;
}
destroy() {
// Clear update interval
if (this.updateInterval) {
clearInterval(this.updateInterval);
}
// Destroy charts
Object.values(this.charts).forEach(chart => {
chart.destroy();
});
// Clear container
this.container.innerHTML = '';
}
}
// Initialize dashboard
document.addEventListener('DOMContentLoaded', function() {
// Set default Chart.js options
Chart.defaults.font.family = 'Arial, sans-serif';
Chart.defaults.color = '#333';
// Create dashboard
window.dashboard = new ChartDashboard('dashboard');
// Make dashboard globally accessible for debugging
console.log('Dashboard initialized:', window.dashboard);
});