Cómo Dibujar Gráficas de Barra Usando JavaScript y Canvas HTML5
() translation by (you can also view the original English article)



En un tutorial anterior cubrimos cómo dibujar una gráfica de pastel o dona usando el canvas HTML5. En este tutorial te mostraré cómo usar JavaScript y el canvas de HTML5 como un modo de mostrar gráficamente datos usando gráficas de barras.
Hay maneras más sencillas para crear gráficas que codificar una desde cero, por ejemplo esta completa librería de graficación desde CodeCanyon.



Pero si quieres saber qué toma crear una librería como esta, este tutorial es para ti.
¿Qué Es una Gráfica de Barra?
Las gráficas de barra son herramientas muy comunes usadas para representar datos numéricos. Desde reportes financieros hasta presentaciones PowerPoint hasta infografías, las gráficas de barra son usadas muy frecuentemente ya que ofrecen una vista de datos numéricos que es muy sencilla de entender.
Las gráficas de barra representan datos numéricos usando barras, las cuáles son rectángulos con sus anchos y altos proporcionales a los datos numéricos que representan.
Hay muchos tipos de gráficas de barras:
- gráficas de barra horizontal y gráficas de barra vertical dependiendo de la orientación de la gráfica
- gráficas de barras apiladas o gráficas de barra clásicas para representar múltiples series de datos
- gráficas de barra 2D o 3D
- etc.
¿Cuáles Son los Componentes de una Gráfica de Barra?
Echemos un vistazo a los componentes que conforman una gráfica de barra independientemente de su tipo:



- Los datos de la gráfica: estos son conjuntos de números y categorías asociadas que las cuáles son representadas por la gráfica.
- Nombre de la serie de datos (1)
- La cuadrícula de gráfica (2): dando un sistema de referencia para que la representación visual pueda ser entendida fácilmente.
- Las barras (3): rectángulos rellenos de color con dimensiones proporcionales a los datos representados.
- Leyenda de gráfica (4): muestra la correspondencia entre los colores usados y los datos que representan.
Ahora que conocemos los componentes de una gráfica de barra, veamos cómo podemos escribir el código JavaScript para dibujar una gráfica como esta.
Dibujando la Gráfica de Barra Usando JavaScript
Configurando el Proyecto JS
Para comenzar a dibujar usando JavaScript y el canvas HTML5, necesitaremos configurar nuestro proyecto como esto:
- Crea una carpeta para contener los archivos del proyecto; nombremos a esta carpeta
bar-chart-tutorial
. - Dentro de la carpeta de proyecto, crea un archivo y nómbralo
index.html
. Este contendrá nuestro código HTML. - También dentro de la carpeta de proyecto, crea un archivo y nómbralo
script.js
. Este contendrá el código JavaScript para dibujar la gráfica de barra.
Mantendremos las cosas bastante sencillas y agregaremos el siguiente código dentro de index.html
:
1 |
<html>
|
2 |
<body>
|
3 |
<canvas id="myCanvas"></canvas> |
4 |
<script type="text/javascript" src="script.js"></script> |
5 |
</body>
|
6 |
</html>
|
Tenemos el elemento <canvas>
con el ID myCanvas
para que podamos referenciarlo en nuestro código JS. Después cargamos el código JS vía la etiqueta <script>
.
Agrega el siguiente código en el archivo script.js
:
1 |
var myCanvas = document.getElementById("myCanvas"); |
2 |
myCanvas.width = 300; |
3 |
myCanvas.height = 300; |
4 |
|
5 |
var ctx = myCanvas.getContext("2d"); |
Esto obtiene una referencia al elemento canvas y después establece el ancho y alto a 300px
. Para dibujar sobre el canvas, solo necesitamos una referencia a su contexto 2D, el cuál contiene todos los métodos de dibujo.
Agregando unas Cuántas Funciones de Ayuda
Dibujar la gráfica de barra solo requiere saber cómo dibujar dos elementos:
- dibujar una línea: para dibujar las líneas de la cuadrícula
- dibujar un rectángulo con color de relleno: para dibujar las barras de la gráfica
Creemos las funciones JS de ayuda para estos dos elementos. Agregaremos las funciones en nuestro archivo script.js
.
1 |
function drawLine(ctx, startX, startY, endX, endY,color){ |
2 |
ctx.save(); |
3 |
ctx.strokeStyle = color; |
4 |
ctx.beginPath(); |
5 |
ctx.moveTo(startX,startY); |
6 |
ctx.lineTo(endX,endY); |
7 |
ctx.stroke(); |
8 |
ctx.restore(); |
9 |
}
|
La función drawLine
toma seis parámetros:
-
ctx
: referencia al contexto de dibujo -
startX
: la coordenada X del punto de inicio de la línea -
startY
: la coordenada Y del punto de inicio de la línea
-
endX
: la coordenada X del punto final de la línea
-
endY
: la coordenada Y del punto final de la línea
-
color
: el color de la línea
Estamos modificando los ajustes de color para el strokeStyle
. Esto determina el color usado para dibujar la línea. Usamos ctx.save()
y ctx.restore()
de manera que no afectamos los colores usados fuera de esta función.
Dibujamos la línea llamando a beginPath()
. Esto informa al contexto de dibujo que estamos comenzando a dibujar algo nuevo sobre el canvas. Usamos moveTo()
para establecer el punto de inicio, llamaos a lineTo()
para indicar el punto final, y después hacemos el dibujo llamando a stroke()
.
Otra función de ayuda que necesitamos es una función para dibujar una barra---la cuál es un rectángulo con color de relleno. Agreguémoslo a script.js
:
1 |
function drawBar(ctx, upperLeftCornerX, upperLeftCornerY, width, height,color){ |
2 |
ctx.save(); |
3 |
ctx.fillStyle=color; |
4 |
ctx.fillRect(upperLeftCornerX,upperLeftCornerY,width,height); |
5 |
ctx.restore(); |
6 |
} |
La función drawBar
toma seis parámetros:
-
ctx
: referencia al contexto de dibujo -
upperLeftCornerX
: la coordenada X de la esquina superior izquierda de la barra -
upperLeftCornerY
: la coordenada Y de la esquina superior izquierda de la barra -
width
: el ancho de la barra
-
height
: la altura de la barra -
color
: el color de la barra
El Modelo de Datos de la Gráfica de Barra
Ahora que tenemos las funciones de ayuda en posición, continuemos al modelo de datos de la gráfica. Todos los tipos de gráfica, incluyendo gráficas de barra, tienen un modelo de datos detrás de ellas. El modelo de datos es un conjunto estructurado de datos numéricos. Para este tutorial usaremos una serie de datos de categorías y sus valores numéricos asociados representando el número de discos de acetato en mi colección de discos agrupados por género musical:
- Música clásica: 10
- Rock alternativo: 14
- Pop: 2
- Jazz: 12
Podemos representar esto en JavaScript en la forma de un objeto. Agreguemos este a nuestro archivo script.js
:
1 |
var myVinyls = { |
2 |
"Classical music": 10, |
3 |
"Alternative rock": 14, |
4 |
"Pop": 2, |
5 |
"Jazz": 12 |
6 |
};
|
Implementando el Componente de Gráfica de Barra
Implementemos el componente que hará el dibujo de nuestra gráfica de barra. Haremos esto agregando el siguiente objeto JavaScript a nuestro archivo script.js
:
1 |
var Barchart = function(options){ |
2 |
this.options = options; |
3 |
this.canvas = options.canvas; |
4 |
this.ctx = this.canvas.getContext("2d"); |
5 |
this.colors = options.colors; |
6 |
|
7 |
this.draw = function(){ |
8 |
var maxValue = 0; |
9 |
for (var categ in this.options.data){ |
10 |
maxValue = Math.max(maxValue,this.options.data[categ]); |
11 |
}
|
12 |
var canvasActualHeight = this.canvas.height - this.options.padding * 2; |
13 |
var canvasActualWidth = this.canvas.width - this.options.padding * 2; |
14 |
|
15 |
//drawing the grid lines
|
16 |
var gridValue = 0; |
17 |
while (gridValue <= maxValue){ |
18 |
var gridY = canvasActualHeight * (1 - gridValue/maxValue) + this.options.padding; |
19 |
drawLine( |
20 |
this.ctx, |
21 |
0, |
22 |
gridY, |
23 |
this.canvas.width, |
24 |
gridY, |
25 |
this.options.gridColor |
26 |
);
|
27 |
|
28 |
//writing grid markers
|
29 |
this.ctx.save(); |
30 |
this.ctx.fillStyle = this.options.gridColor; |
31 |
this.ctx.font = "bold 10px Arial"; |
32 |
this.ctx.fillText(gridValue, 10,gridY - 2); |
33 |
this.ctx.restore(); |
34 |
|
35 |
gridValue+=this.options.gridScale; |
36 |
}
|
37 |
|
38 |
//drawing the bars
|
39 |
var barIndex = 0; |
40 |
var numberOfBars = Object.keys(this.options.data).length; |
41 |
var barSize = (canvasActualWidth)/numberOfBars; |
42 |
|
43 |
for (categ in this.options.data){ |
44 |
var val = this.options.data[categ]; |
45 |
var barHeight = Math.round( canvasActualHeight * val/maxValue) ; |
46 |
drawBar( |
47 |
this.ctx, |
48 |
this.options.padding + barIndex * barSize, |
49 |
this.canvas.height - barHeight - this.options.padding, |
50 |
barSize, |
51 |
barHeight, |
52 |
this.colors[barIndex%this.colors.length] |
53 |
);
|
54 |
|
55 |
barIndex++; |
56 |
}
|
57 |
|
58 |
}
|
59 |
}
|
La clase comienza almacenando las options
pasadas como parámetros. Esta almacena la referencia canvas
y crea un contexto de dibujo también almacenado como un miembro de clase. Después almacena el arreglo colors
pasado como opciones.
La siguiente parte es la más consistente, la función draw()
. Esta dibujará la gráfica dibujando primero las líneas de cuadrícula, los marcadores de cuadrícula y después las barras usando los parámetros pasados vía el objeto options
.
Viendo la función draw()
, podemos ver que primero calculamos el valor máximo para nuestro modelo de datos. Necesitamos este número porque necesitamos escalar todas las barras de acuerdo a este valor y de acuerdo al tamaño del canvas. De otro modo, nuestras barras podrían salir del área de visión, y no queremos eso.
Las variables canvasActualHeight
y canvasActualWidth
almacenan la altura y anchura del canvas ajustado usando el valor del padding pasado vía options
. La variable padding
indica el número de pixeles entre el borde del canvas y la gráfica dentro.
Entonces dibujamos las líneas de cuadrícula de la gráfica. La variable options.gridScale
establece el paso usado para dibujar las líneas. Así que un gridScale
de 10 significará dibujar líneas de cuadrícula cada 10 unidades.
Para dibujar las líneas de cuadrícula, usamos la función de ayuda drawLine()
; para el color de las líneas de cuadrícula, lo tomamos de la variable options.gridColor
. Por favor nota que las coordenadas del canvas comienzan desde 0,0
en la esquina superior izquierda y se incrementan hacia la derecha y abajo, mientras que nuestros valores de cuadrícula se incrementan en valor desde el fondo hacia arriba. Es por esto que usamos 1 - gridValue/maxValue
en la formula calculando el valor gridY
.
Para cada línea de cuadrícula, también dibujamos el valor de la línea de cuadrícula dos pixeles arriba de la línea de cuadrícula (es por eso que tenemos gridY - 2
para las coordenadas Y del texto).
Después dibujamos las barras usando la función de ayuda drawBar()
. Las matemáticas para calcular el alto y ancho de cada barra son bastante sencillas; estas toman en cuenta el padding y el valor y color para cada categoría en el modelo de datos de la gráfica.
Usando el Componente de Gráfica de Barra
Ahora veamos cómo usar la clase Barchart
implementada arriba. Necesitamos instanciar la clase y llamar la función draw()
. Agrega el siguiente código al archivo script.js
:
1 |
var myBarchart = new Barchart( |
2 |
{
|
3 |
canvas:myCanvas, |
4 |
padding:10, |
5 |
gridScale:5, |
6 |
gridColor:"#eeeeee", |
7 |
data:myVinyls, |
8 |
colors:["#a55ca5","#67b6c7", "#bccd7a","#eb9743"] |
9 |
}
|
10 |
);
|
11 |
myBarchart.draw(); |
El código crea una nueva instancia de la clase Barchart
con las opciones requeridas. Cargar el index.html
en un navegador debería producir un resultado como este:



Agregando el Nombre de Serie de Datos y Leyenda de Gráfica
Para agregar el nombre de la serie de datos debajo de la gráfica, necesitamos agregar el siguiente código en el archivo script.js
después del for-loop
que dibuja la barra:
1 |
...
|
2 |
//drawing series name
|
3 |
this.ctx.save(); |
4 |
this.ctx.textBaseline="bottom"; |
5 |
this.ctx.textAlign="center"; |
6 |
this.ctx.fillStyle = "#000000"; |
7 |
this.ctx.font = "bold 14px Arial"; |
8 |
this.ctx.fillText(this.options.seriesName, this.canvas.width/2,this.canvas.height); |
9 |
this.ctx.restore(); |
10 |
...
|
También necesitamos cambiar la manera en que llamamos al componente Barchart
de este modo:
1 |
var myBarchart = new Barchart( |
2 |
{
|
3 |
canvas:myCanvas, |
4 |
seriesName:"Vinyl records", |
5 |
padding:20, |
6 |
gridScale:5, |
7 |
gridColor:"#eeeeee", |
8 |
data:myVinyls, |
9 |
colors:["#a55ca5","#67b6c7", "#bccd7a","#eb9743"] |
10 |
}
|
11 |
);
|
12 |
myBarchart.draw(); |
Y aquí está cómo luce el resultado:



Para agregar la leyenda, primero necesitamos modificar index.html
para que luzca así:
1 |
<html>
|
2 |
<body>
|
3 |
<canvas id="myCanvas" style="background: white;"></canvas> |
4 |
<legend for="myCanvas"></legend> |
5 |
<script type="text/javascript" src="script.js"></script> |
6 |
</body>
|
7 |
</html>
|
La etiqueta leyenda
será usada como un contenedor para la leyenda de la gráfica. El atributo for
enlaza la leyenda al canvas conteniendo la gráfica. Ahora necesitamos agregar el código que crea la leyenda. Haremos esto en el archivo index.js
después del código que dibuja el nombre de la serie de datos. El código identifica la etiqueta legend
correspondiente a la gráfica, y agregará la lista de categorías desde el modelo de datos de la gráfica junto con el color correspondiente. El archivo index.js
resultante lucirá como esto:
1 |
var myCanvas = document.getElementById("myCanvas"); |
2 |
myCanvas.width = 300; |
3 |
myCanvas.height = 300; |
4 |
|
5 |
var ctx = myCanvas.getContext("2d"); |
6 |
|
7 |
function drawLine(ctx, startX, startY, endX, endY,color){ |
8 |
ctx.save(); |
9 |
ctx.strokeStyle = color; |
10 |
ctx.beginPath(); |
11 |
ctx.moveTo(startX,startY); |
12 |
ctx.lineTo(endX,endY); |
13 |
ctx.stroke(); |
14 |
ctx.restore(); |
15 |
}
|
16 |
|
17 |
function drawBar(ctx, upperLeftCornerX, upperLeftCornerY, width, height,color){ |
18 |
ctx.save(); |
19 |
ctx.fillStyle=color; |
20 |
ctx.fillRect(upperLeftCornerX,upperLeftCornerY,width,height); |
21 |
ctx.restore(); |
22 |
}
|
23 |
|
24 |
var myVinyls = { |
25 |
"Classical music": 10, |
26 |
"Alternative rock": 14, |
27 |
"Pop": 2, |
28 |
"Jazz": 12 |
29 |
};
|
30 |
|
31 |
var Barchart = function(options){ |
32 |
this.options = options; |
33 |
this.canvas = options.canvas; |
34 |
this.ctx = this.canvas.getContext("2d"); |
35 |
this.colors = options.colors; |
36 |
|
37 |
this.draw = function(){ |
38 |
var maxValue = 0; |
39 |
for (var categ in this.options.data){ |
40 |
maxValue = Math.max(maxValue,this.options.data[categ]); |
41 |
}
|
42 |
var canvasActualHeight = this.canvas.height - this.options.padding * 2; |
43 |
var canvasActualWidth = this.canvas.width - this.options.padding * 2; |
44 |
|
45 |
//drawing the grid lines
|
46 |
var gridValue = 0; |
47 |
while (gridValue <= maxValue){ |
48 |
var gridY = canvasActualHeight * (1 - gridValue/maxValue) + this.options.padding; |
49 |
drawLine( |
50 |
this.ctx, |
51 |
0, |
52 |
gridY, |
53 |
this.canvas.width, |
54 |
gridY, |
55 |
this.options.gridColor |
56 |
);
|
57 |
|
58 |
//writing grid markers
|
59 |
this.ctx.save(); |
60 |
this.ctx.fillStyle = this.options.gridColor; |
61 |
this.ctx.textBaseline="bottom"; |
62 |
this.ctx.font = "bold 10px Arial"; |
63 |
this.ctx.fillText(gridValue, 10,gridY - 2); |
64 |
this.ctx.restore(); |
65 |
|
66 |
gridValue+=this.options.gridScale; |
67 |
}
|
68 |
|
69 |
//drawing the bars
|
70 |
var barIndex = 0; |
71 |
var numberOfBars = Object.keys(this.options.data).length; |
72 |
var barSize = (canvasActualWidth)/numberOfBars; |
73 |
|
74 |
for (categ in this.options.data){ |
75 |
var val = this.options.data[categ]; |
76 |
var barHeight = Math.round( canvasActualHeight * val/maxValue) ; |
77 |
drawBar( |
78 |
this.ctx, |
79 |
this.options.padding + barIndex * barSize, |
80 |
this.canvas.height - barHeight - this.options.padding, |
81 |
barSize, |
82 |
barHeight, |
83 |
this.colors[barIndex%this.colors.length] |
84 |
);
|
85 |
|
86 |
barIndex++; |
87 |
}
|
88 |
|
89 |
//drawing series name
|
90 |
this.ctx.save(); |
91 |
this.ctx.textBaseline="bottom"; |
92 |
this.ctx.textAlign="center"; |
93 |
this.ctx.fillStyle = "#000000"; |
94 |
this.ctx.font = "bold 14px Arial"; |
95 |
this.ctx.fillText(this.options.seriesName, this.canvas.width/2,this.canvas.height); |
96 |
this.ctx.restore(); |
97 |
|
98 |
//draw legend
|
99 |
barIndex = 0; |
100 |
var legend = document.querySelector("legend[for='myCanvas']"); |
101 |
var ul = document.createElement("ul"); |
102 |
legend.append(ul); |
103 |
for (categ in this.options.data){ |
104 |
var li = document.createElement("li"); |
105 |
li.style.listStyle = "none"; |
106 |
li.style.borderLeft = "20px solid "+this.colors[barIndex%this.colors.length]; |
107 |
li.style.padding = "5px"; |
108 |
li.textContent = categ; |
109 |
ul.append(li); |
110 |
barIndex++; |
111 |
}
|
112 |
}
|
113 |
}
|
114 |
|
115 |
|
116 |
var myBarchart = new Barchart( |
117 |
{
|
118 |
canvas:myCanvas, |
119 |
seriesName:"Vinyl records", |
120 |
padding:20, |
121 |
gridScale:5, |
122 |
gridColor:"#eeeeee", |
123 |
data:myVinyls, |
124 |
colors:["#a55ca5","#67b6c7", "#bccd7a","#eb9743"] |
125 |
}
|
126 |
);
|
Lo que producirá un resultado final que luce como esto:



Felicidades
Hemos visto que dibujar gráficas usando el canvas HTML5 de hecho no es tan difícil. Solo requiere un poco de matemáticas y un poco de conocimiento JavaScript. Ahora tienes todo lo que necesitas para dibujar tus propias gráficas de barra.
Si quieres una solución rápida y sencilla para crear no solo gráficas de barra, sino montones de otros tipos de gráficas, puedes descargar la Librería de Etiquetas HTML de Gráficas e Infografías o su contraparte de complemento WordPress Diseñador Visual de Gráficas WordPress.


