Volver al inicio
Anexo: Chart.js

Chart.js para KPIs

Aprende a crear graficas profesionales para tus dashboards con Chart.js, la libreria mas popular para visualizacion de datos en JavaScript vanilla.

1 ΒΏQue es Chart.js?

Chart.js es una libreria de JavaScript open-source que dibuja graficas sobre un elemento <canvas> del HTML. Es ligera (~60KB gzipped), responsive por defecto, y soporta 8 tipos de graficas listas para usar.

🎨 Analogia del mundo real:

Chart.js es como una impresora de planos: tΓΊ le pasas los datos (medidas) y la configuraciΓ³n (escala, colores, leyenda), y ella se encarga de dibujar. No te preocupas por calcular pΓ­xeles ni curvas: tΓΊ piensas en quΓ© quieres comunicar, ella lo dibuja.

Caracteristicas clave:

  • β€’Canvas API: dibuja sobre pixeles, no sobre el DOM. Rinde mejor con muchos puntos.
  • β€’Responsive: se adapta solo al tamano del contenedor padre.
  • β€’Animaciones fluidas: transiciones entre cambios de datos out-of-the-box.
  • β€’Tree-shakeable: en v4 puedes importar solo lo que uses.
  • β€’Sin dependencias: no necesita jQuery ni nada.

2 ΒΏPor que es ideal para KPIs?

Un KPI (Key Performance Indicator) necesita comunicar una metrica en segundos. Chart.js te da lo justo para eso:

πŸ“ˆ Tendencias

Line charts para ver evolucion temporal: ventas por dia, sesiones por hora.

πŸ“Š Comparaciones

Bar charts para comparar categorias: ingresos por canal, productos mas vendidos.

πŸ₯§ Distribuciones

Doughnut/pie para ver proporciones: conversion rate, market share.

🎯 Multi-metrica

Radar charts para evaluar un objeto por varias dimensiones a la vez.

3 Instalacion

Tienes dos caminos para incluir Chart.js en tu proyecto. ElΓ­gelo segun el contexto:

Recomendado

A) npm

Para proyectos reales con bundler (Vite, Webpack, Astro, Next, etc). Es como vas a trabajar siempre en una empresa.

Pros: tree-shaking, versionado, autocompletado del IDE, funciona offline. Contras: requiere tener Node y un bundler.

B) CDN

Para prototipos rapidos, demos, codepen, HTML simple sin bundler.

Pros: cero setup, una linea y listo. Contras: no hay tree-shaking, depende de internet, no escala a proyectos grandes.

Opcion A β€” npm (recomendada)

Es la forma profesional. AcostΓΊmbrate a trabajar asΓ­: las librerΓ­as se instalan, no se copian de un CDN. Te queda registrada en package.json, puedes versionarla, el IDE te autocompleta y funciona offline.

1npm install chart.js

Y en tu archivo JS:

1import Chart from 'chart.js/auto';

chart.js/auto registra TODOS los componentes (escalas, controllers, plugins). Es lo mΓ‘s cΓ³modo para arrancar. Para bundles mΓ­nimos en producciΓ³n, puedes importar solo lo que uses.

Opcion B β€” CDN (solo para prototipos)

Pega esto antes de cerrar </body> en tu HTML:

1<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>

Esto te deja la variable global Chart disponible en cualquier script que cargues despues. Útil para experimentar rÑpido, pero no es lo que vas a usar en un proyecto real.

πŸ’‘ ΒΏPor que npm es mejor?

En cuanto trabajes en un proyecto real con Astro, React, Vue o cualquier framework moderno, vas a tener un bundler. AcostΓΊmbrate desde ya: npm install + import. Es la base de todo el ecosistema JS moderno y lo que vas a hacer con CADA librerΓ­a de aquΓ­ en adelante.

4 Tu primera grafica paso a paso

Crear una grafica son 4 pasos. Vamos uno por uno con un caso real: graficar las ventas mensuales.

1

Crear el canvas en el HTML

Chart.js dibuja sobre un <canvas>. Ponele un id para poder referenciarlo desde JS. Importante: envuΓ©lvelo en un contenedor con tamaΓ±o definido.

1<div style="max-width: 600px; height: 400px;">
2 <canvas id="miGrafica"></canvas>
3</div>
2

Cargar / importar Chart.js

Con npm (recomendado), instΓ‘lalo y luego impΓ³rtalo en tu archivo JS:

1npm install chart.js
1import Chart from 'chart.js/auto';

O si estΓ‘s usando CDN en un HTML simple, agrΓ©galo antes de cerrar </body>:

1<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.1/dist/chart.umd.min.js"></script>
2<script src="./app.js"></script>
3

Obtener la referencia al canvas

Igual que con cualquier elemento del DOM, usa document.getElementById:

1const ctx = document.getElementById('miGrafica');

La variable se llama ctx por convencion (de "context"), aunque Chart.js v3+ acepta directamente el elemento canvas.

4

Instanciar el objeto Chart

Crea una nueva instancia con new Chart(ctx, config). El segundo parametro es el objeto de configuracion con 3 propiedades: type, data y options.

1const grafica = new Chart(ctx, {
2 type: 'line',
3 data: {
4 labels: ['Ene', 'Feb', 'Mar', 'Abr', 'May'],
5 datasets: [{
6 label: 'Ventas 2026',
7 data: [120, 190, 300, 250, 420],
8 borderColor: 'rgb(168, 85, 247)',
9 backgroundColor: 'rgba(168, 85, 247, 0.2)',
10 fill: true,
11 tension: 0.4
12 }]
13 },
14 options: {
15 responsive: true,
16 plugins: {
17 legend: { position: 'top' },
18 title: { display: true, text: 'Ventas mensuales' }
19 }
20 }
21});

βœ… Listo. Chart.js ya dibujΓ³ la grΓ‘fica en el canvas. Si abres el HTML en el navegador, la ves animada.

πŸ’‘ Resumen del paso a paso:

  1. Canvas en HTML con id
  2. Cargar Chart.js (CDN o import)
  3. getElementById para la referencia
  4. new Chart(ctx, { type, data, options })

5 Anatomia: type, data y options

Toda configuracion de Chart.js sigue exactamente la misma estructura. Estos son los 3 parametros que controlan todo:

1new Chart(ctx, {
2 type: '...', // QUE tipo de grafica dibujar
3 data: { ... }, // QUE datos mostrar (labels + datasets)
4 options: { ... } // COMO se ve y comporta (colores, ejes, leyendas, animaciones)
5});

type β€” los 8 tipos disponibles

Un string que define el tipo de grafica. Estos son TODOS los valores posibles:

type Para que sirve Ejemplo de uso en KPI
'line'Linea continua entre puntosIngresos por dia, sesiones por hora
'bar'Barras verticales (u horizontales con indexAxis)Ventas por canal, top productos
'pie'Torta clasicaDistribucion del presupuesto
'doughnut'Torta con agujero (donut)Conversion rate, completitud
'radar'Grafico de areas multidimensionalPerformance multi-area, skills
'polarArea'Como pie pero con segmentos de longitud variableDistribucion ponderada
'bubble'Burbujas con tamano variable (3 dimensiones)Precio vs volumen vs margen
'scatter'Puntos sueltos en un plano XYCorrelacion entre 2 metricas

data β€” los datos a mostrar

Es un objeto con dos propiedades: labels (etiquetas del eje X) y datasets (uno o varios conjuntos de datos a graficar).

1data: {
2 labels: ['Ene', 'Feb', 'Mar'], // string[] β€” eje X
3 datasets: [
4 {
5 label: 'Producto A', // nombre que aparece en la leyenda
6 data: [10, 20, 30], // number[] β€” los valores
7 backgroundColor: '...',
8 borderColor: '...',
9 // ...mas propiedades de estilo
10 },
11 {
12 label: 'Producto B',
13 data: [15, 25, 35],
14 }
15 ]
16}

Propiedades comunes de un dataset:

Propiedad Tipo Que hace
labelstringTexto que aparece en la leyenda y en tooltips
datanumber[]El array de valores a graficar
backgroundColorstring | string[]Color de relleno (uno solo o uno por punto)
borderColorstring | string[]Color del borde / linea
borderWidthnumberGrosor del borde en px
fillboolean(line) Pintar el area bajo la linea
tensionnumber 0-1(line) Curvatura: 0 = recto, 0.4 = suave
pointRadiusnumber(line) Tamano de los puntos. 0 = sin puntos
borderRadiusnumber(bar) Esquinas redondeadas en las barras

options β€” como se ve y comporta

Las opciones controlan TODO lo visual y de comportamiento. Aca van las mas usadas:

Opcion Valores Para que
responsivetrue | falseSe adapta al contenedor padre
maintainAspectRatiotrue | falseMantiene proporcion. false = llena el contenedor
indexAxis'x' | 'y'(bar) 'y' = barras horizontales
cutout'50%' | number(doughnut) Tamano del agujero
animation{ duration, easing } | falseVelocidad y tipo de transicion
plugins.legend{ display, position }Leyenda: 'top'|'bottom'|'left'|'right'
plugins.title{ display, text }Titulo arriba del grafico
plugins.tooltip{ enabled, callbacks }Tooltips al hacer hover
scales.y{ beginAtZero, min, max }Configuracion del eje Y
scales.x{ display, grid }Configuracion del eje X

Valores comunes de animation.easing:

'linear' 'easeInQuad' 'easeOutQuad' 'easeInOutQuad' 'easeInCubic' 'easeOutCubic' 'easeInOutQuart' 'easeOutBounce'

6 Ejemplo completo con TODOS los parametros

Esta es una grafica de tipo line con 2 datasets, cada parametro comentado. CΓ³pialo, pΓ©galo en un HTML con un <canvas id="ventas"></canvas> y funcionarΓ‘:

1const ctx = document.getElementById('ventas');
2
3const grafica = new Chart(ctx, {
4 // ─────────────────────────────────────────────────────
5 // PARAMETRO 1: type β€” que tipo de grafica
6 // ─────────────────────────────────────────────────────
7 type: 'line',
8
9 // ─────────────────────────────────────────────────────
10 // PARAMETRO 2: data β€” los datos
11 // ─────────────────────────────────────────────────────
12 data: {
13 labels: ['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun'],
14
15 datasets: [
16 {
17 label: 'Producto A', // nombre en leyenda
18 data: [120, 190, 300, 250, 420, 380], // valores
19
20 borderColor: 'rgb(168, 85, 247)', // color de la linea
21 backgroundColor: 'rgba(168, 85, 247, 0.2)', // relleno
22 borderWidth: 3, // grosor en px
23
24 fill: true, // pintar area bajo la linea
25 tension: 0.4, // curvatura (0 = recto)
26 pointRadius: 4, // tamano de puntos
27 pointHoverRadius: 6, // tamano al hacer hover
28 pointBackgroundColor: 'rgb(168, 85, 247)',
29 },
30 {
31 label: 'Producto B',
32 data: [80, 150, 220, 310, 280, 350],
33 borderColor: 'rgb(236, 72, 153)',
34 backgroundColor: 'rgba(236, 72, 153, 0.2)',
35 borderWidth: 3,
36 fill: true,
37 tension: 0.4,
38 }
39 ]
40 },
41
42 // ─────────────────────────────────────────────────────
43 // PARAMETRO 3: options β€” como se ve y comporta
44 // ─────────────────────────────────────────────────────
45 options: {
46 responsive: true, // se adapta al contenedor
47 maintainAspectRatio: false, // llena todo el contenedor
48
49 // Animaciones
50 animation: {
51 duration: 1000, // ms
52 easing: 'easeInOutQuart' // tipo de curva
53 },
54
55 // Plugins (leyenda, titulo, tooltip)
56 plugins: {
57 legend: {
58 display: true,
59 position: 'top', // top|bottom|left|right
60 labels: { color: '#e2e8f0', font: { size: 13 } }
61 },
62 title: {
63 display: true,
64 text: 'Ventas mensuales 2026',
65 color: '#f1f5f9',
66 font: { size: 18, weight: 'bold' }
67 },
68 tooltip: {
69 enabled: true,
70 backgroundColor: 'rgba(15, 23, 42, 0.95)',
71 titleColor: '#f1f5f9',
72 bodyColor: '#cbd5e1',
73 callbacks: {
74 // Personalizar el texto del tooltip
75 label: (ctx) => `${ctx.dataset.label}: $${ctx.parsed.y}`
76 }
77 }
78 },
79
80 // Configuracion de los ejes
81 scales: {
82 y: {
83 beginAtZero: true,
84 min: 0,
85 max: 500,
86 ticks: { color: '#94a3b8', stepSize: 100 },
87 grid: { color: 'rgba(148, 163, 184, 0.1)' },
88 title: { display: true, text: 'Ventas ($)' }
89 },
90 x: {
91 ticks: { color: '#94a3b8' },
92 grid: { display: false },
93 title: { display: true, text: 'Mes' }
94 }
95 }
96 }
97});

πŸ’‘ Nota:

NO necesitas escribir todos los parametros. Chart.js tiene defaults razonables. Este ejemplo te muestra TODO lo que puedes ajustar. En la prΓ‘ctica, una config tΓ­pica tiene 5-10 lΓ­neas.

7 Actualizar datos en vivo (el corazon de un dashboard)

Un KPI sin datos frescos es un cadaver. Chart.js expone .update() para repintar con animaciΓ³n cuando cambias el array de datos.

El patron: mutar + update()

1const grafica = new Chart(ctx, {
2 type: 'line',
3 data: { labels: [], datasets: [{ label: 'Usuarios', data: [] }] }
4});
5
6function tick() {
7 const ahora = new Date().toLocaleTimeString();
8 const valor = Math.floor(Math.random() * 100) + 50;
9
10 // Agregamos el nuevo punto
11 grafica.data.labels.push(ahora);
12 grafica.data.datasets[0].data.push(valor);
13
14 // Mantenemos solo los ultimos 20
15 if (grafica.data.labels.length > 20) {
16 grafica.data.labels.shift();
17 grafica.data.datasets[0].data.shift();
18 }
19
20 grafica.update(); // anima la transicion
21}
22
23setInterval(tick, 1500); // cada 1.5s

⚑ Gotcha clasico:

NO reemplaces grafica.data = nuevosData sin mas: rompe las referencias internas. Muta los arrays existentes (con push/shift/splice) o asigna a grafica.data.datasets[0].data. Despues, .update().

8 Integrar en Astro (JS vanilla, sin React)

En Astro puedes escribir JS vanilla dentro de un bloque <script> al final del .astro. Astro lo procesa y lo manda al browser. No necesitas ni React ni componentes.

1---
2// src/pages/dashboard.astro
3---
4<canvas id="ventas"></canvas>
5
6<script>
7 import Chart from 'chart.js/auto';
8
9 const ctx = document.getElementById('ventas');
10
11 const grafica = new Chart(ctx, {
12 type: 'line',
13 data: {
14 labels: [],
15 datasets: [{ label: 'Ventas', data: [], borderColor: '#a855f7' }]
16 }
17 });
18
19 setInterval(() => {
20 grafica.data.labels.push(new Date().toLocaleTimeString());
21 grafica.data.datasets[0].data.push(Math.random() * 100);
22 if (grafica.data.labels.length > 15) {
23 grafica.data.labels.shift();
24 grafica.data.datasets[0].data.shift();
25 }
26 grafica.update();
27 }, 1000);
28</script>

πŸ’‘ Tip Astro:

Si uses is:inline en el script, Astro NO lo procesa: tienes que cargar Chart.js por CDN. Sin is:inline, Astro usa Vite y puedes importar chart.js/auto.

9 Buenas practicas

βœ“

Contenedor con tamano explicito

Envolve el <canvas> en un div con width/height. Si no, Chart.js se va a pantalla completa.

βœ“

Limita puntos en graficas en vivo

Mantene solo los ultimos N puntos (shift). Un array infinito mata el render.

βœ“

Limpia el interval

Si la grafica se desmonta (SPA, navegacion), llama clearInterval y grafica.destroy(). Sino, fuga de memoria.

⚠️

No abuses de animaciones

Si actualizas cada 500ms, desactiva animaciones con options.animation = false o uses update('none').

⚠️

Cuidado con el dark mode

Los colores por defecto (labels, grids) son para fondo blanco. Configura Chart.defaults.color y Chart.defaults.borderColor.

10 Resumen

  • β€’Chart.js dibuja sobre <canvas>: ligero, responsive, sin dependencias.
  • β€’4 pasos: canvas β†’ cargar Chart β†’ getElementById β†’ new Chart(ctx, config).
  • β€’Toda config tiene type + data + options. type es uno de los 8 tipos disponibles.
  • β€’Para KPIs: line (tendencia), bar (comparacion), doughnut (proporcion), radar (multi-dimension).
  • β€’Actualizar en vivo = mutar arrays + llamar update(), nunca reemplazar data.