En este tutorial, le mostraré cómo usar JavaScript y el lienzo como un medio para mostrar información numérica en forma de gráficos circulares y gráficos de anillos..
Hay formas más fáciles de crear gráficos que codificando uno desde cero, por ejemplo, esta completa biblioteca de gráficos de CodeCanyon.
Biblioteca de gráficos de CodeCanyonPero si quieres saber qué sucede detrás de las escenas en una biblioteca como esta, sigue leyendo.
Un gráfico es una herramienta estadística utilizada para representar gráficamente datos numéricos. Un gráfico circular muestra esos datos numéricos como un círculo dividido en segmentos. El tamaño de cada sector es proporcional al valor numérico que representa.
En pocas palabras, un gráfico de anillos es una variación del gráfico circular. La diferencia es que las rebanadas se cortan hacia el centro del pastel, de modo que solo se ve el borde. De esta manera, el gráfico se ve como una dona y por lo tanto el nombre.
Antes de dibujar el gráfico circular, veremos cómo dibujar sus partes. Veremos cómo podemos usar el componente de lienzo y JavaScript para dibujar:
Para comenzar a dibujar usando el lienzo HTML5, necesitaremos crear algunas cosas:
piechart-tutorial
.index.html
dentro de piechart-tutorial
carpeta. Este archivo contendrá el código HTML.script.js
dentro de piechart-tutorial
carpeta. Este archivo contendrá nuestro código JavaScript.Mantendremos las cosas muy simples y agregaremos el siguiente código dentro index.html
:
Tenemos el elemento con el ID
myCanvas
para que podamos referenciarlo en nuestro código JS. Luego cargamos el código JS a través de tag.
Inside script.js
, the JS code will first get a reference to the canvas and then set its width and height. To draw on the canvas, we only need a reference to its 2D context which contains all the drawing methods.
var myCanvas = document.getElementById("myCanvas"); myCanvas.width = 300; myCanvas.height = 300; var ctx = myCanvas.getContext("2d");
Now that we have canvas set up and also a reference to the drawing canvas, let's define a few JavaScript functions that we will be able to reuse when drawing the pie chart. We will add the functions in our script.js file.
function drawLine(ctx, startX, startY, endX, endY) ctx.beginPath(); ctx.moveTo(startX,startY); ctx.lineTo(endX,endY); ctx.stroke();
The drawLine
function takes five parameters:
ctx
: reference to the drawing contextstartX
: the X coordinate of the line starting pointstartY
: the Y coordinate of the line starting pointendX
: the X coordinate of the line end pointendY
: the Y coordinate of the line end pointWe start drawing the line by calling beginPath()
. This informs the drawing context that we are starting to draw something new on the canvas. We use moveTo()
to set the starting point, call lineTo()
to indicate the end point, and then do the actual drawing by calling stroke()
.
Let's now see how we can draw a part of a circle, also called an arc.
function drawArc(ctx, centerX, centerY, radius, startAngle, endAngle) ctx.beginPath(); ctx.arc(centerX, centerY, radius, startAngle, endAngle); ctx.stroke();
The drawArc
function takes six parameters:
ctx
: reference to the drawing contextcenterX
: the X coordinate of the circle centercenterY
: the Y coordinate of the circle centerradius
: the X coordinate of the line end pointstartAngle
: the start angle in radians where the portion of the circle startsendAngle
: the end angle in radians where the portion of the circle endsWe've seen how to draw a line and how to draw an arc, so now let's see how to draw a colored shape. Since our goal is to draw a pie chart that is made up of slices, let's create a function that draws a pie slice.
function drawPieSlice(ctx,centerX, centerY, radius, startAngle, endAngle, color ) ctx.fillStyle = color; ctx.beginPath(); ctx.moveTo(centerX,centerY); ctx.arc(centerX, centerY, radius, startAngle, endAngle); ctx.closePath(); ctx.fill();
The drawPieSlice
function takes seven parameters:
ctx
: reference to the drawing contextcenterX
: the X coordinate of the circle centercenterY
: the Y coordinate of the circle centerradius
: the X coordinate of the line end pointstartAngle
: the start angle in radians where the portion of the circle startsendAngle
: the end angle in radians where the portion of the circle endscolor
: the color used to fill the sliceHere is an example for calling three functions:
drawLine(_ctx,100,100,200,200); drawArc(_ctx, 150,150,150, 0, Math.PI/3); drawPieSlice(_ctx, 150,150,150, Math.PI/2, Math.PI/2 + Math.PI/4, '#ff0000');
It will produce this result:
Now we have all the tools necessary to draw a pie chart, so let's see how we use them together.
Conceptually, any chart has two main parts:
The most common way to structure the data model for pie charts is a series of categories and corresponding values, where each of the categories and values are associated to a slice of the pie.
As an example, the data model of a pie chart displaying the number of vinyls I have grouped by genre would look something like:
We can add a JS object to the script.js
file to store the data model like this:
var myVinyls = "Classical music": 10, "Alternative rock": 14, "Pop": 2, "Jazz": 12 ;
The pie chart uses a circle to display the information in the data model by dividing it into slices. Each slice corresponds to a category from the data model, and the size of the slice is proportional to the category value.
My small collection of 38 vinyls has four categories. Each category will get a slice of the pie chart proportional to the number of vinyls in that category.
But how do we measure the size of a slice? That's easy-we do that by the angle at the tip of the slice. All we have to know is that the full circle corresponds to an angle of 360 degrees
or 2 * PI
. So half a circle would be 180 deg
or PI
, a quarter 90 deg
or PI/2
, and so on.
For determining the angle for each category slice, we use the formula:
slice angle = 2 * PI * category value / total value
According to this formula, the ten classical music vinyls will get a slice angle of approx. 0.526 * PI or 94 deg.
Let's get to drawing. For this we will use a JavaScript class which we will name Piechart
. The constructor will receive one options argument, an object containing the following:
The Piechart
class also contains one method draw()
which does the actual drawing of the chart.
var Piechart = function(options) this.options = options; this.canvas = options.canvas; this.ctx = this.canvas.getContext("2d"); this.colors = options.colors; this.draw = function() var total_value = 0; var color_index = 0; for (var categ in this.options.data) var val = this.options.data[categ]; total_value += val; var start_angle = 0; for (categ in this.options.data) val = this.options.data[categ]; var slice_angle = 2 * Math.PI * val / total_value; drawPieSlice( this.ctx, this.canvas.width/2, this.canvas.height/2, Math.min(this.canvas.width/2,this.canvas.height/2), start_angle, start_angle+slice_angle, this.colors[color_index%this.colors.length] ); start_angle += slice_angle; color_index++;
The class starts by storing the options
passed as parameters. It stores the canvas
reference and creates a drawing context also stored as a class member. Then it stores the colors
array passed as options.
The next part is the most consistent, the draw()
function. This will draw the data from the data model. First it calculates the sum of all values in the data model. Then, for each category in the data model we apply the formula mentioned above for calculating the pie slice angle. Finally we use the drawPieSlice()
function using the center of the canvas as the center of the slice. As a radius we use the minimum value between half of the canvas width and half of the canvas height since we don't want our pie to go out of the canvas.
We also offset the start and end angle of the slices each time we draw a category, otherwise the slices would overlap.
To use the class, we have to create an instance and then call the draw()
method on the created object.
var myPiechart = new Piechart( canvas:myCanvas, data:myVinyls, colors:["#fde23e","#f16e23", "#57d9ff","#937e88"] ); myPiechart.draw();
And the result looks like this
We've seen how to draw the pie chart. We also know that a doughnut chart differs only by having a hole in the middle of the chart. How do we draw the hole? We can draw a white circle over the pie chart.
Let's modify the code of the Piechart
class to do that.
var Piechart = function(options) this.options = options; this.canvas = options.canvas; this.ctx = this.canvas.getContext("2d"); this.colors = options.colors; this.draw = function() var total_value = 0; var color_index = 0; for (var categ in this.options.data) var val = this.options.data[categ]; total_value += val; var start_angle = 0; for (categ in this.options.data) val = this.options.data[categ]; var slice_angle = 2 * Math.PI * val / total_value; drawPieSlice( this.ctx, this.canvas.width/2, this.canvas.height/2, Math.min(this.canvas.width/2,this.canvas.height/2), start_angle, start_angle+slice_angle, this.colors[color_index%this.colors.length] ); start_angle += slice_angle; color_index++; //drawing a white circle over the chart //to create the doughnut chart if (this.options.doughnutHoleSize) drawPieSlice( this.ctx, this.canvas.width/2, this.canvas.height/2, this.options.doughnutHoleSize * Math.min(this.canvas.width/2,this.canvas.height/2), 0, 2 * Math.PI, "#ff0000" );
The added code looks in the options
parameter for a member variable doughnutHoleSize
. If this doesn't exist in the options then the code will draw the pie chart as before, but if it does exist then a white circle is drawn with the same center as the pie chart.
The radius of the circle is determined by multiplying the pie chart radius and the value of doughnutHoleSize
. This should be a number between 0 and 1, where 0 will result in a pie chart and any values higher than 0 would result in a doughnut with the hole larger and larger, 1 making the chart invisible.
To draw a doughnut chart with a hole half the size of the chart, we would need to use a doughnutHoleSize
of 0.5 and make the following calls:
var myDougnutChart = new Piechart( canvas:myCanvas, data:myVinyls, colors:["#fde23e","#f16e23", "#57d9ff","#937e88"], doughnutHoleSize:0.5 ); myDougnutChart.draw();
And here is the result:
Our pie chart and doughnut chart look pretty good, but we can make them even better by adding two things:
Usually, values associated with the slices are represented as percentage values calculated as 100 * value associated to a slice / total value
, with the whole circle representing 100%
.
For example, in the case of our sample data, vinyls with classical music would represent approximately 26%
. It would be nice to be able to write that value right on the corresponding slice. To do that, we will use the fillText(text,x,y)
function of the drawing context. This function takes three parameters: the text and the x
and y
coordinates.
How do we calculate the x
and y
coordinates at which to place the text? We have to make use of some geometry knowledge and something called polar coordinates. Basically, polar coordinates use a radius and an angle to define the position of a point. The two formulas we will use are:
x = R * cos(angle)
y = R * sin(angle)
We will apply these two formulas to place the text halfway along the pie chart radius and halfway around the angle for each pie slice. To do this, we need to modify our Piechart
class and add the following code right after the if (this.options.doughnutHoleSize)…
block:
… start_angle = 0; for (categ in this.options.data) val = this.options.data[categ]; slice_angle = 2 * Math.PI * val / total_value; var pieRadius = Math.min(this.canvas.width/2,this.canvas.height/2); var labelX = this.canvas.width/2 + (pieRadius / 2) * Math.cos(start_angle + slice_angle/2); var labelY = this.canvas.height/2 + (pieRadius / 2) * Math.sin(start_angle + slice_angle/2); if (this.options.doughnutHoleSize) var offset = (pieRadius * this.options.doughnutHoleSize ) / 2; labelX = this.canvas.width/2 + (offset + pieRadius / 2) * Math.cos(start_angle + slice_angle/2); labelY = this.canvas.height/2 + (offset + pieRadius / 2) * Math.sin(start_angle + slice_angle/2); var labelText = Math.round(100 * val / total_value); this.ctx.fillStyle = "white"; this.ctx.font = "bold 20px Arial"; this.ctx.fillText(labelText+"%", labelX,labelY); start_angle += slice_angle; …
The code goes over each slice, calculates the percentage, calculates the position, and uses the fillText()
method to draw it on the chart. We have used the fillStyle
property to set the text color to white and the font
property to set the size, style and font family of the label. It's also important to note that if the chart is a doughnut chart and the doughnutHoleSize
is set, then the label will be pushed towards the edge of the chart to make it centered on the doughnut slice.
And here's how the resulting charts look with the value labels:
To complete our chart, the last thing we will add is the chart legend. Our chart legend will display the categories of our data model and the color used for the corresponding slice. First we have to make some modifications to our Entonces en El código busca un También necesitamos hacer un cambio en la forma en que llamamos el dibujo de nuestro gráfico circular de esta manera: Y aquí está el gráfico resultante y la leyenda del gráfico: Hemos visto que dibujar gráficos utilizando el lienzo HTML5 no es realmente tan difícil. Solo requiere un poco de matemática y un poco de conocimiento de JavaScript. Ahora tiene todo lo que necesita para dibujar sus propios gráficos circulares y gráficos de anillos.. Si desea una solución rápida y fácil para crear no solo gráficos circulares y gráficos de anillos sino también muchos otros tipos de gráficos, puede descargar la Biblioteca de etiquetas HTML de gráficos infográficos o sus contrapartes del complemento de WordPress Gráficos y tablas de WordPress.index.html
file by adding a
script.js
Añadimos el código que crea el contenido del elemento de leyenda. Añadimos este código al final del dibujar()
función de la Gráfico circular
clase:... if (this.options.legend) color_index = 0; var legendHTML = ""; para (categorizar en this.options.data) legendHTML + = "
leyenda
elemento pasado a través de la opciones
parámetro. Si se proporciona uno, este elemento se completa con el código HTML que contiene un cuadro de color y el nombre de la categoría de modelo de datos.var myLegend = document.getElementById ("myLegend"); var myDougnutChart = new Piechart (canvas: myCanvas, data: myVinyls, colors: ["# fde23e", "# f16e23", "# 57d9ff", "# 937e88"], leyenda: myLegend); myDougnutChart.draw ();
Felicidades