Ahora que sabemos sobre SVG y data binding, podemos crear un gráfico de barras. Vamos a usar el siguiente arreglo de datos para crear nuestro gráfico. Vamos a partir graficando la cantidad de calorías de cada alimento.
Vamos a crear un elemento SVG y definir su tamaño.
var svg = d3.select('#example-a02').append('svg')
.attr('width', 600)
.attr('height', 80)
.attr('id', 'svg-ejemplo-a02');
Ahora creamos la selección para los rectángulos, vinculando los rectángulos al arreglo de datos. Vamos a usar la misma secuencia que en el ejemplo de la sección previa.
// Data binding
var rect = svg.selectAll('rect').data(data);
// Agregamos los rectángulos a la selección enter.
rect.enter().append('rect')
.attr('x', 200)
.attr('y', function(d, i) { return 20 * i; })
.attr('width', 0)
.attr('height', 20 - 2)
.attr('fill', 'blue');
// Actualizamos los atributos de los rectángulos
rect.transition().duration(2000)
.attr('width', function(d) { return d.calorias; });
// Eliminamos los rectángulos sin datos
rect.exit().remove();
Notar que en este caso, no necesitamos remover elementos, pero es buena práctica remover los elementos de la selección exit para cuando queramos revincular la selección a otro conjunto de datos.
Podemos agregar etiquetas a cada rectángulo. Vamos a poner el nombre de cada categoría alineado a la izquierda de cada rectángulo.
// Data binding
var labels = svg.selectAll('text.label').data(data);
// Agrega las etiquetas a la selección enter
labels.enter().append('text')
.attr('class', 'label')
.attr('x', 190)
.attr('y', function(d, i) { return 20 * (i + 1) - 5; })
.attr('text-anchor', 'end')
.text(function(d) { return d.nombre; });
// Elimina las etiquetas en exit
labels.exit().remove();
Además, vamos a poner el número de calorías de cada barra dentro de la barra.
// Data binding
var count = svg.selectAll('text.count').data(data);
// Agrega las etiquetas a la selección enter
count.enter().append('text')
.attr('class', 'count')
.attr('x', function(d) { return d.calorias + 200 - 5; })
.attr('y', function(d, i) { return 20 * (i + 1) - 5; })
.attr('fill', 'white')
.attr('text-anchor', 'end')
.text(function(d) { return d.calorias; });
// Elimina las etiquetas en exit
count.exit().remove();
Graficando Otra Variable
Podemos actualizar los atributos de las selecciones existentes para graficar otra variable de cada alimento. Por ejemplo, podemos graficar el contenido de proteína.
// Actualizamos el ancho y color de los rectángulos
rect.transition().duration(2000)
.attr('fill', 'yellow')
.attr('width', function(d) { return d.proteinas; });
// Actualiza la posición del count con transición
count.transition().duration(2000)
.attr('x', function(d) { return d.proteinas + 200 + 5; });
// Actualiza otros atributos instantáneamente
count
.attr('fill', 'black')
.attr('text-anchor', 'start')
.text(function(d) { return d.proteinas; });
En este ejemplo, usamos el valor de cada variable (calorías y proteínas) para determinar el largo de los rectángulos. Normalmente, esto no es muy práctico, ya que las barras podrían quedar muy chicas o muy grandes. Para optimizar el uso del espacio, podemos usar escalas, que son el tópico de la próxima sección.