Error: Canvas is already in use. Chart with ID '0' must be destroyed before the canvas with ID 'ingresoChart' can be reused.
Causa: El dashboard se estaba inicializando múltiples veces, creando conflictos entre instancias de Chart.js que intentaban usar el mismo canvas.
class DashboardManager {
constructor() {
// Prevenir múltiples inicializaciones
if (window.dashboardManagerInstance) {
console.log('⚠️ DashboardManager ya está inicializado, retornando instancia existente');
return window.dashboardManagerInstance;
}
// Marcar como instancia global
window.dashboardManagerInstance = this;
this.init();
}
}
Beneficios:
limpiarGraficos() {
// Destruir gráficos existentes si existen
if (this.charts.ingresos) {
this.charts.ingresos.destroy();
this.charts.ingresos = null;
}
if (this.charts.distribucion) {
this.charts.distribucion.destroy();
this.charts.distribucion = null;
}
// Limpiar el objeto de gráficos
this.charts = {};
console.log('🧹 Gráficos limpiados correctamente');
}
Beneficios:
crearGraficoIngresos() {
const ctx = document.getElementById('ingresoChart');
if (!ctx) {
console.log('⚠️ Canvas ingresoChart no encontrado, omitiendo gráfico de ingresos');
return;
}
// Verificar que el canvas no esté siendo usado por otro gráfico
if (ctx.chart) {
console.log('⚠️ Canvas ingresoChart ya tiene un gráfico, destruyendo el anterior...');
ctx.chart.destroy();
ctx.chart = null;
}
try {
this.charts.ingresos = new Chart(ctx, { /* ... */ });
// Marcar el canvas como usado por este gráfico
ctx.chart = this.charts.ingresos;
console.log('✅ Gráfico de ingresos creado correctamente');
} catch (error) {
console.error('❌ Error creando gráfico de ingresos:', error);
this.charts.ingresos = null;
}
}
Beneficios:
async init() {
// Prevenir múltiples inicializaciones
if (this.inicializado) {
console.log('⚠️ DashboardManager ya está inicializado, omitiendo...');
return;
}
try {
// ... código de inicialización ...
this.inicializado = true;
console.log('✅ Dashboard Manager inicializado correctamente');
} catch (error) {
console.error('❌ Error inicializando Dashboard:', error);
}
}
Beneficios:
// Método global para acceder al dashboard de forma segura
window.getDashboardManager = () => {
if (window.dashboardManagerInstance) {
return window.dashboardManagerInstance;
}
if (window.DashboardManager) {
try {
return new window.DashboardManager();
} catch (error) {
console.error('❌ Error creando nueva instancia de DashboardManager:', error);
return null;
}
}
return null;
};
Beneficios:
// Usar el patrón singleton - solo crear si no existe
if (!window.dashboardManagerInstance) {
window.dashboardManager = new window.DashboardManager();
console.log('✅ Dashboard Manager inicializado correctamente');
} else {
console.log('✅ Dashboard Manager ya existe, usando instancia existente');
window.dashboardManager = window.dashboardManagerInstance;
}
Beneficios:
js/dashboard.jsindex.htmltest_dashboard_charts_fixed.html (Nuevo)test_dashboard_charts_fixed.html
Si persisten problemas:
dashboard.js se cargue después de Chart.jsEstado: ✅ RESUELTO
Fecha: $(date)
Versión: Dashboard v2.0 (Con patrón singleton y manejo seguro de charts)