Advertisement
  1. Web Design
  2. HTML/CSS
  3. HTML

Cómo Dibujar Gráficas Usando JavaScript y Canvas HTML5

Scroll to top
Read Time: 15 min

() translation by (you can also view the original English article)

Final product imageFinal product imageFinal product image
What You'll Be Creating

En este tutorial te mostraré cómo usar JavaScript y el canvas como medios para mostrar información numérica en la forma de gráficas de pastel y gráficas de dona.

Hay maneras más fáciles de crear gráficas que codificar una desde cero, por ejemplo esta librería completa de graficación de CodeCanyon.

Infographic charts and graphics HTML tags libraryInfographic charts and graphics HTML tags libraryInfographic charts and graphics HTML tags library
Librería de gráficas de CodeCanyon

Pero si quieres saber que sucede tras bambalinas en una librería como esta, sigue leyendo.

¿Qué Es una Gráfica de Pastel?

Una gráfica es una herramienta estadística usada para representar gráficamente datos numéricos. Una gráfica de pastel muestra datos numéricos como un círculo dividido en rebanadas. EL tamaño de cada rebanada es proporcional al valor numérico que representa.

¿Qué Es una Gráfica de Dona?

Para ponerlo en términos simples, una gráfica de dona es una variación de la gráfica de pastel. La diferencia es que las rebanadas son cortadas en el centro del pastel de manera que solo el borde es visible. De esta manera, la gráfica se ve como una dona y de ahí el nombre.

Comenzando a Dibujar con el Canvas

Antes de dibujar la gráfica de pastel, echaremos un vistazo a dibujar sus partes. Veremos cómo podemos usar el componente canvas y JavaScript para dibujar:

  • un línea
  • un arco (una parte de un círculo)
  • una figura con relleno de color

Para comenzar usando el canvas de HTML5, necesitaremos crear unas cuantas cosas:

  • Una carpeta para contener los archivos del proyecto; llamemos a este folder piechart-tutorial.
  • Un archivo HTML index.html dentro de la carpeta piechart-tutorial. Este archivo contendrá el código HTML.
  • Un archivo JS script.js dentro de la carpeta piechart-tutorial. Este archivo contendrá nuestro código JavaScript.

Mantendremos las cosas bastante simples y agregaremos el siguiente código dentro de index.html:

1
<html>
2
3
<body>
4
5
    <canvas id="myCanvas"></canvas>
6
7
  <script type="text/javascript" src="script.js"></script>
8
9
</body>
10
11
</html>

Tenemos el elemento <canvas> con el ID myCanvas para que podamos referenciarlo en nuestro código JS. Entonces podemos cargar nuestro código JS por medio de la etiqueta <script>.

Dentro de script.js, el código JS primero obtendrá una referencia al canvas y después establecerá su anchura y altura. Para dibujar en el canvas, solo necesitamos una referencia a su context 2D el cuál contiene todos los métodos de dibujo.

1
var myCanvas = document.getElementById("myCanvas");
2
3
myCanvas.width = 300;
4
5
myCanvas.height = 300;
6
7
8
9
var ctx = myCanvas.getContext("2d");

Ahora que tenemos el canvas configurado y también una referencia al canvas de dibujo, definamos unas cuantas fuciones JavaScript que podremos reusar cuando dibujemos la gráfica de pastel. Agregaremos las funciones en nuestro archivo script.js.

1
function drawLine(ctx, startX, startY, endX, endY){
2
3
    ctx.beginPath();
4
5
	ctx.moveTo(startX,startY);
6
7
	ctx.lineTo(endX,endY);
8
9
	ctx.stroke();
10
11
}

La función drawLine toma cinco parámetros:

  1. ctx: referencia al contexto de dibujo
  2. startX: la coordenada X de la línea de punto de inicio
  3. startY: la coordenada Y de la línea de punto de inicio
  4. endX: la coordenada X de la línea de punto de inicio
  5. endY: la coordenada Y de la línea de punto de inicio

Comenzamos dibujando la línea llamando beginPath(). Esto informa al contexto de dibujo que estamos comenzando a dibujar algo nuevo en el canvas. Usamos moveTo() para establecer el punto de partida, llmamos lineTo() para indicar el punto final y después hacemos el dibujo en cuestión llamando a stroke().

Veamos ahora cómo podemos dibujar una parte de un círculo, también llamado arco.

1
function drawArc(ctx, centerX, centerY, radius, startAngle, endAngle){
2
3
    ctx.beginPath();
4
5
	ctx.arc(centerX, centerY, radius, startAngle, endAngle);
6
7
	ctx.stroke();
8
9
}

La función drawArc toma seis parámetros:

  1. ctx: referencia al contexto del dibujo
  2. centerX: la coordenada X del centro del círculo
  3. centerY: la coordenada Y del centro del círculo
  4. radio: la coordenada X de la línea del punto final
  5. startAngle: el ángulo inicial en radianes en donde comienza la porción del círculo
  6. endAngle: el ángulo final en radianes en donde termina la porción del círculo

Hemos visto como dibujar una línea y cómo dibujar un arco, así que veamos ahora cómo dibujar una figura coloreada. Ya que nuestra meta es dibujar una gráfica de pastel que está hecha de rebanadas, creemos una función que dibuja una rebanada del pastel.

1
function drawPieSlice(ctx,centerX, centerY, radius, startAngle, endAngle, color ){
2
3
    ctx.fillStyle = color;
4
5
	ctx.beginPath();
6
7
	ctx.moveTo(centerX,centerY);
8
9
	ctx.arc(centerX, centerY, radius, startAngle, endAngle);
10
11
	ctx.closePath();
12
13
	ctx.fill();
14
15
}

La función dwarPieSlice toma siete parámetros:

  1. ctx: referencia al contexto del dibujo
  2. centerX: la coordenada X del centro del círculo
  3. centerY: la coordenada Y del centro del círculo
  4. radio: la coordenada X de la línea del punto final
  5. startAngle: el ángulo inicial en radianes en donde comienza la porción del círculo
  6. endAngle: el ángulo final en radianes en donde termina la porción final del círculo
  7. color: el color usado para rellenar la rebanada

Aquí hay un ejemplo para llamar tres funciones:

1
drawLine(_ctx,100,100,200,200);
2
3
drawArc(_ctx, 150,150,150, 0, Math.PI/3);
4
5
drawPieSlice(_ctx, 150,150,150, Math.PI/2, Math.PI/2 + Math.PI/4, '#ff0000');

Producirá el resultado:

Canvas line arc and pie sliceCanvas line arc and pie sliceCanvas line arc and pie slice

Ahora tenemos todas las herramientas necesarias para dibujar la gráfica de pastel, así que veamos como usarlas juntas.

Dibujando la Gráfica de Pastel

Conceptualmente, cualquier gráfica tiene dos partes principales:

  • El modelo de datosc contiene la información numérica a ser representada. Esta está estructurada en un formato específico al tipo de gráfica.
  • La representación gráfica es cómo la información numérica en el modelo de datos es representada por elementos visuales de acuerdo a ciertas reglas en la forma de fórmulas matemáticas.

El Modelo de Datos de Gráfica de Pastel

La forma más común de estructurar modelos de datos para gráficas de pastel es una serie de categorías y valores correspondientes, en donde cada una de las categorías y valores son asociados a una rebanada del pastel.

Como ejemplo, el modelo de datos de una gráfica de pastel que muestra el número de vinilos que tengo agrupados por género se vería como:

  • Música clásica: 10
  • Rock alternativo: 14
  • Pop: 2
  • Jazz: 12

Podemos agregar un objeto de JS al archivo script.js para almacenar el modelo de datos como esto:

1
var myVinyls = {
2
3
    "Classical music": 10,
4
5
	"Alternative rock": 14,
6
7
	"Pop": 2,
8
9
	"Jazz": 12
10
11
};

La Representación Gráfica de Gráfica de Pastel

La gráfica de pastel usa un círculo para mostrar la información en el modelo de datos dividiéndolo en rebanadas. Cada rebanada corresponde a una categoría del modelo de datos y el tamaño de la rebanada es proporcional al valor de la categoría.

Mi pequeña colección de 38 vinilos tiene cuatro categorías. Cada categoría tendrá una rebanada de la gráfica de pastel proporcional al número de vinilos en esa categoría.

¿Pero cómo medimos el tamaño de la rebanada? Es sencillo--lo hacemos con el ángulo en la punta de la rebanada. Todo lo que tenemos que saber es que el círculo completo corresponde a un ángulo de 360 grados o 2 * PI. Así que la mitad del círculo sería 180 grados o PI, un cuarto 90 grados o PI/2 y así sucesívamente.

Para determinar el ángulo para cada rebanada de categoría, usamos la fórmula:

ángulo de rebanada = 2 * PI * valor de categoría / valor total

De acuerdo a esta fórmula, los diez vinilos de música clásica tendrán un ángulo de aprox. 0.526 * PI ó 94 grados.

Comencemos a dibujar. Para este usaremos una clase javaScript la cuál nombraremos Piechart. El contructor recibirá un argumento opciones, un objeto conteniendo lo siguiente:

  • canvas: referencia al canvas en donde queremos dibujar la gráfica de pastel
  • data: referencia de un objeto conteniendo el modelo de datos
  • colors: un arreglo conteniendo los colores que queremos usar para cada rebanada

La clase Piechart también contiene un método draw() el cuál hace el dibujo de la gráfica.

1
var Piechart = function(options){
2
3
    this.options = options;
4
5
	this.canvas = options.canvas;
6
7
	this.ctx = this.canvas.getContext("2d");
8
9
	this.colors = options.colors;
10
11
12
13
	this.draw = function(){
14
15
		var total_value = 0;
16
17
		var color_index = 0;
18
19
		for (var categ in this.options.data){
20
21
			var val = this.options.data[categ];
22
23
			total_value += val;
24
25
		}
26
27
28
29
		var start_angle = 0;
30
31
		for (categ in this.options.data){
32
33
			val = this.options.data[categ];
34
35
			var slice_angle = 2 * Math.PI * val / total_value;
36
37
38
39
			drawPieSlice(
40
41
				this.ctx,
42
43
				this.canvas.width/2,
44
45
				this.canvas.height/2,
46
47
				Math.min(this.canvas.width/2,this.canvas.height/2),
48
49
				start_angle,
50
51
				start_angle+slice_angle,
52
53
				this.colors[color_index%this.colors.length]
54
55
			);
56
57
58
59
			start_angle += slice_angle;
60
61
			color_index++;
62
63
		}
64
65
66
67
	}
68
69
}

La clase comienza almacenando las options pasadas como argumentos. Esta almacena la referencia de canvas y crea un contexto de dibujo también almacenado como un miembro de la clase. Después almacena el arreglo colors pasado como opciones.

La siguiente parte es la más consistente, la función draw(). Esto dibujará los datos del modelo de datos. Primero calcula la suma de todos los valores en el modelo de datos. Después, para cada categoría en el modelo de datos aplicamos la fórmula mencionada arriba para calcular el ángulo de la rebanada. Finalmente usamos la función drawPieSlice() usando el centro del canvas como el centro de la rebanada. Como radio usamos el valor mínimo entre la mitad del ancho del canvas y la mitad del alto ya que no queremos que nuestro pastel salga del canvas.

También compensamos el inicio y el final de las rebanadas cada vez que dibujamos una categoría, de otro modo las rebanadas se encimarían.

Para usar esta clase, tenemos que crear una instancia y después llamar el método draw() en el objeto creado.

1
var myPiechart = new Piechart(
2
3
    {
4
5
		canvas:myCanvas,
6
7
		data:myVinyls,
8
9
		colors:["#fde23e","#f16e23", "#57d9ff","#937e88"]
10
11
	}
12
13
);
14
15
myPiechart.draw();

Y el resultado se ve así

Drawing a pie chart using HTML5 canvasDrawing a pie chart using HTML5 canvasDrawing a pie chart using HTML5 canvas

Dibujando la Gráfica de Dona

Hemos visto cómo dibujar la gráfica de pastel También sabemos que una gráfica de dona difiere solo por tener un agujero en medio de la gráfica. ¿Cómo dibujamos el agujero? Podemos dibujar un círculo blanco sobre la gráfica de pastel.

Modifiquemos el código de la clase Piechart para hacer eso.

1
var Piechart = function(options){
2
3
    this.options = options;
4
5
	this.canvas = options.canvas;
6
7
	this.ctx = this.canvas.getContext("2d");
8
9
	this.colors = options.colors;
10
11
12
13
	this.draw = function(){
14
15
		var total_value = 0;
16
17
		var color_index = 0;
18
19
		for (var categ in this.options.data){
20
21
			var val = this.options.data[categ];
22
23
			total_value += val;
24
25
		}
26
27
28
29
		var start_angle = 0;
30
31
		for (categ in this.options.data){
32
33
			val = this.options.data[categ];
34
35
			var slice_angle = 2 * Math.PI * val / total_value;
36
37
38
39
			drawPieSlice(
40
41
				this.ctx,
42
43
				this.canvas.width/2,
44
45
				this.canvas.height/2,
46
47
				Math.min(this.canvas.width/2,this.canvas.height/2),
48
49
				start_angle,
50
51
				start_angle+slice_angle,
52
53
				this.colors[color_index%this.colors.length]
54
55
			);
56
57
58
59
			start_angle += slice_angle;
60
61
			color_index++;
62
63
		}
64
65
66
67
        //drawing a white circle over the chart

68
69
        //to create the doughnut chart

70
71
		if (this.options.doughnutHoleSize){
72
73
			drawPieSlice(
74
75
				this.ctx,
76
77
				this.canvas.width/2,
78
79
				this.canvas.height/2,
80
81
				this.options.doughnutHoleSize * Math.min(this.canvas.width/2,this.canvas.height/2),
82
83
				0,
84
85
				2 * Math.PI,
86
87
				"#ff0000"
88
89
			);
90
91
		}
92
93
94
95
	}
96
97
}

El código agregado busca en el parámetro options por un miembro variable doughnutHoleSize. Si este no existe en las opciones entonces el código dibujará la gráfica de pastel como antes, pero si existe entonces se dibujará un círculo blanco con el mism centro que la gráfica de pastel.

El radio del círculo es determinado por multiplicar el radio de la gráfica de pastel y el valor de doughnutHoleSize. Esto debería ser un numero entre 0 y 1, en donde 0 será el resultado en una gráfica de pastel y cualquier valor más alto que 0 resultaría en una dona con el agujero más grande y más grande, 1 haciendo la gráfica invisible.

Para dibujar una gráfica de dona con un agujero del tamaño de la tabla, necesitaríamos usar un doughnutHoleSize de 0.5 y hacer las siguientes llamadas.

1
var myDougnutChart = new Piechart(
2
3
    {
4
5
		canvas:myCanvas,
6
7
		data:myVinyls,
8
9
		colors:["#fde23e","#f16e23", "#57d9ff","#937e88"],
10
11
		doughnutHoleSize:0.5
12
13
	}
14
15
);
16
17
myDougnutChart.draw();

Y aquí está el resultado:

drawing a doughnut chart with HTML5 canvasdrawing a doughnut chart with HTML5 canvasdrawing a doughnut chart with HTML5 canvas

Agregando Etiquetas y Leyenda de Gráfica

Nuestra gráfica de pastel y dona se ven muy bien, pero podemos hacerlas mucho mejor agregando dos cosas:

  • etiquetas de valor: mostrando el porcentaje correspondiente a cada rebanada
  • una leyenda de gráfica: mostrando las categorías y sus colores correspondientes en la gráfica

Usualmente, valoes asociados con las rebanadas son representadas como valores porcentuales calculados como 100* valor asociado a la rebanada / valor total, con el círculo completo representando 100%.

Por ejemplo, en el caso de nuestros datos de muestra, vinilos con música clásica representaría aproximádamente 26%. Sería agradable poder escribir ese valor justo en la rebanada correspondiente. Para hacer eso, usaremos la función fillText(text,x,y) del contexto del diibujo. Esta función toma tres parámetros: el texto y las coordenadas x y y.

¿Cómo calculamos las coordenadas x y y en las cuáles colocar el texto? Tenemos que hacer uso de un poco de conocimiento de geometría y algo llamado coordenadas polares. Básicamente, las coordenadas polares usan un radio y un ángulo para definir la posición de un punto. Las dos fórmulas que usaremos son:

x = R * cos(ángulo)

y = R * sin(ángulo)

Aplicaremos estas dos fórmulas para colocar el texto a la mitad del radio de la gráfica de pastel y a la mitad del ángulo para cada rebanada del pastel. Para hacer esto, necesitamos modificar nuestra clase Piechart y agregar el siguiente código justo después del bloque (this.options.doughnutHoleSize){...}:

1
        ...
2
3
        start_angle = 0;
4
5
		for (categ in this.options.data){
6
7
			val = this.options.data[categ];
8
9
			slice_angle = 2 * Math.PI * val / total_value;
10
11
			var pieRadius = Math.min(this.canvas.width/2,this.canvas.height/2);
12
13
			var labelX = this.canvas.width/2 + (pieRadius / 2) * Math.cos(start_angle + slice_angle/2);
14
15
			var labelY = this.canvas.height/2 + (pieRadius / 2) * Math.sin(start_angle + slice_angle/2);
16
17
18
19
			if (this.options.doughnutHoleSize){
20
21
				var offset = (pieRadius * this.options.doughnutHoleSize ) / 2;
22
23
				labelX = this.canvas.width/2 + (offset + pieRadius / 2) * Math.cos(start_angle + slice_angle/2);
24
25
				labelY = this.canvas.height/2 + (offset + pieRadius / 2) * Math.sin(start_angle + slice_angle/2);				
26
27
			}
28
29
30
31
			var labelText = Math.round(100 * val / total_value);
32
33
			this.ctx.fillStyle = "white";
34
35
			this.ctx.font = "bold 20px Arial";
36
37
			this.ctx.fillText(labelText+"%", labelX,labelY);
38
39
			start_angle += slice_angle;
40
41
		}
42
43
        ...

El código recorre cada rebanada, calcula el porcentaje, calcula la posición y usa el método fillText() para dibujarla en la gráfica. Hemos usado la propiedad fillStyle para establecer el color dle texto a blanco y la propiedad font para establecer el tamaño, estilo y familia tipográfica de la etiqueta. También es importante notar que si la gráfica es una gráfica de dona y el doughnutHoleSize está establecido, entonces la etiqueta será empujada hacia el borde de la gráfica para centrarla en la rebanada de la dona.

Y aquí está cómo se ven las gráficas resultantes con las etiquetas de valor:

Pie chart and doughnut chart with value labelsPie chart and doughnut chart with value labelsPie chart and doughnut chart with value labels

Para completar nuestra gráfica, la última cosa que agregaremos es la leyenda de la gráfica. Nuestra leyenda mostrará las categorías de nuestro modelo de datos y el color usado para la rebanada correspondiente. Primero tenemos que hacer algunas modificaciones a nuestro archivo index.html agregando una etiqueta <div> que almacenará nuestro elemento leyenda.

1
<html>
2
3
<body>
4
5
    <canvas id="myCanvas"></canvas>
6
7
	<div id="myLegend"></div>
8
9
	<script type="text/javascript" src="script.js"></script>
10
11
</body>
12
13
</html>

Después en script.js agregamos el código que crea el contenido del elemento de leyenda. Agregamos este código al final de la función draw() en la clase Piechart.

1
...
2
3
        if (this.options.legend){
4
5
			color_index = 0;
6
7
			var legendHTML = "";
8
9
			for (categ in this.options.data){
10
11
				legendHTML += "<div><span style='display:inline-block;width:20px;background-color:"+this.colors[color_index++]+";'>&nbsp;</span> "+categ+"</div>";
12
13
			}
14
15
			this.options.legend.innerHTML = legendHTML;
16
17
		}
18
19
...

El código busca el elemeto de legend pasado por medio del parámetro de options. Si uno es proporcionado, este elemento es llenado con el código HTML conteniendo una caja coloreada y el nombre de la categoría del modelo de datos.

También necesitamos hacer un cambio a la manera en que cambiamos el dibujo en un nuestra gráfica de pastel como esto:

1
var myLegend = document.getElementById("myLegend");
2
3
4
5
var myDougnutChart = new Piechart(
6
7
    {
8
9
		canvas:myCanvas,
10
11
		data:myVinyls,
12
13
		colors:["#fde23e","#f16e23", "#57d9ff","#937e88"],
14
15
		legend:myLegend
16
17
	}
18
19
);
20
21
myDougnutChart.draw();

Y aquí están la gráfica y leyenda de gráfica resultantes:

Pie chart with value labels and chart legendPie chart with value labels and chart legendPie chart with value labels and chart legend

Felicidades

Hemos visto que dibujar gráficas usando el canvas HTML5 en realidad no es tan difícil. Solo se requiere un poco de matemáticas y un poco de conocimiento de JavaScript. Ahora tienes todo lo que necesitas para dibujar tu propia gráfica de pastel y dona.

Si quieres una solución rápida y sencilla para crear no solo gráficas de pastel y dona sino montones de otros tipos de gráficas, puedes descargar la Infographic Charts and Graphics HTML Tags Library o su contraparte de plugin para WordPress Charts and Graphs WordPress Visual Designer.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.