13 – Fazer um gráfico de barras

Link para o tutorial original: http://alignedleft.com/tutorials/d3/making-a-bar-chart

Fazer um gráfico de barras

Última actualização 30 de Dezembro de 2012

Vamos agora incorporar tudo o que aprendemos até agora para gerar um gráfico de barras simples com D3.

Comecemos por rever o gráfico de barras que fizemos em vez disso utilizando elementos div. Depois adaptaremos este código para desenhar as barras com SVG, dando-nos mais flexibilidade na apresentação visual. Finalmente, vamos adicionar etiquetas, para ver os valores mais claramente.

O antigo gráfico

Aqui está o que tínhamos da última vez, com novos dados.

var dataset = ;d3.select("body").selectAll("div") .data(dataset) .enter() .append("div") .attr("class", "bar") .style("height", function(d) { var barHeight = d * 5; return barHeight + "px"; });

Gráfico de barras com divs

Pode ser difícil de imaginar, mas podemos claramente melhorar este gráfico de barras simpe feito com divs.

O novo gráfico

P>Primeiro, precisamos de definir o tamanho do novo SVG:

// Largeur et hauteurvar w = 500;var h = 100;

(Claro, poderia chamar w e h algo mais, como svgWidth e svgHeight. Use o que pensa ser mais claro. O JavaScript tem uma cultura de eficiência, pelo que verá frequentemente variáveis de um único carácter, código escrito sem espaços, e outras sintaxes difíceis de ler, mas programmaticamente eficientes.)

Então dizemos a D3 para criar um elemento SVG vazio e adicionamo-lo ao DOM:

// Crée l'élément SVGvar svg = d3.select("body") .append("svg") .attr("width", w) .attr("height", h);

Isto insere um novo <svg> elemento imediatamente antes do fecho </body> tag, e atribui ao SVG as dimensões de 500 por 100 pixels. Esta declaração também coloca o resultado numa nova variável chamada svg, para que possamos facilmente referenciar o SVG sem ter de o voltar a seleccionar mais tarde usando algo como d3.select(“svg”).

Então, em vez de criarmos mergulhos, geramos rects e adicionamo-los ao svg.

svg.selectAll("rect") .data(dataset) .enter() .append("rect") .attr("x", 0) .attr("y", 0) .attr("width", 20) .attr("height", 100);

Este código selecciona todos os rects dentro do svg. Claro que ainda não há nenhum, por isso uma selecção vazia é devolvida. (Esquisito, admito que sim, mas fica comigo. Com D3, tem sempre de seleccionar qualquer coisa em que queira trabalhar, mesmo que essa selecção esteja vazia.)

Next, data(dataet) vê que tem 20 valores no conjunto de dados, pelo que chama enter() 20 vezes. enter(), por sua vez, retorna uma selecção de espaço reservado para cada elemento de dados que não tenha um recto correspondente – o que significa todos os rects.

Para cada um dos 20 espaços reservados, anexar(“recto”) insere um recto no DOM. Como aprendemos na introdução ao SVG, cada recto deve ter valores x, y, largura, e altura definidos. Usamos attr() para adicionar estes atributos em cada um dos rect.

É bonito, não é?

Uma barra solitária

Okay, não tenho a certeza. Todas as barras estão presentes (veja o DOM na página de demonstração com o seu inspector web), mas todas elas partilham os mesmos valores x, y, largura e altura, com o resultado de que todas elas se sobrepõem. Isto ainda não é visualização de dados.

Vamos primeiro corrigir o facto de que eles se sobrepõem. Em vez de utilizarmos um x de zero, atribuir-lhe-emos um valor dinâmico que corresponde a i, a posição de cada elemento do conjunto de dados. Assim a primeira barra será zero, mas as barras seguintes serão 21, depois 42, e assim por diante.

.attr("x", function(d, i) { return i * 21; // Largeur de barre de 20 plus 1 pour la marge})

Vinte barras

Aqui está o código em acção.

Funciona, mas não é super flexível. Se tivéssemos mais dados, as barras seguiriam umas às outras à direita, mesmo após o fim do SVG! Uma vez que cada barra tem 20 pixels de largura, mais 1 pixel de margem, um SVG de 500 pixels de largura só poderia exibir 23 elementos de dados. Note como a 24ª barra é cortada:

Vinte e quatro barras

Uma boa prática é usar coordenadas flexíveis e dinâmicas – alturas, larguras, x-valores, e y-valores – de modo a que a sua visualização seja redimensionada adequadamente com base nos seus dados.

Se houver algum problema na programação, há mil maneiras de o conseguir. Vou usar uma simples. Primeiro, vou mudar a linha onde definimos a posição x de cada barra:

.attr("x", function(d, i) { return i * (w / dataset.length);})

Nota como o valor de x está agora directamente ligado à largura SVG (w) e ao número de valores no nosso conjunto de dados (dataset.length). Isto é excitante, porque agora as nossas barras serão espaçadas uniformemente, quer tenhamos vinte barras:

Vinte barras espaçadas uniformemente

ou apenas cinco:

Cinco barras espaçadas uniformemente

Este é o código até agora.

Agora também devemos tornar as larguras das barras proporcionais, para que fiquem mais finas à medida que se adicionam mais dados, ou mais largas quando há menos valores. Vou adicionar uma nova variável ao lado de onde definimos a altura e largura do SVG

// Largeur et hauteurvar w = 500;var h = 100;var barPadding = 1; // <-- Nouveau !

então faça referência a esta variável na linha onde definimos a largura de cada barra. Em vez de um valor estático de 20, a largura será agora definida como uma fracção entre a largura SVG e a contagem de dados, menos o valor da margem:

.attr("width", w / dataset.length - barPadding)

Vinte barras espaçadas com larguras dinâmicas

Funciona! As larguras e x-posições das barras escalam correctamente se existem vinte pontos, apenas cinco

Cinco barras espaçadas com larguras dinâmicas

ou mesmo cem :

Cem barras espaçadas com larguras dinâmicas

Para terminar, vamos programar a altura de cada barra. Espera-se que isto seja tão fácil como referenciar o valor d ao definir a altura:

.attr("height", function(d) { return d;});

Altura dinâmica

Hum, isso soa a funky. Talvez pudéssemos fazer os nossos números um pouco maiores?

.attr("height", function(d) { return d * 4; // <-- Fois quatre !});

Altura Dinâmica

Alas, não é assim tão fácil – queremos que as nossas barras cresçam a partir da extremidade inferior, não a partir da extremidade superior – mas não culpe D3, culpe SVG.

Remmbrar da introdução ao SVG: ao desenhar rects, os valores x e y especificam as coordenadas do canto superior esquerdo. Isto significa que a origem ou ponto de referência de cada recto é o seu ponto superior esquerdo. Para os nossos propósitos, seria teeeeeellly mais fácil se o nosso ponto de referência fosse o ponto inferior esquerdo, mas não é assim que a SVG funciona, e, francamente, a SVG é bastante indiferente aos seus sentimentos sobre o assunto.

Desde que as nossas barras devem “crescer a partir do topo”, onde está “o topo” de cada barra em relação ao topo da SVG? Bem, a parte superior de cada barra pode ser definida como uma relação entre a altura do SVG e o valor dos dados correspondentes, assim:

.attr("y", function(d) { return h - d; // Hauteur moins la valeur de la donnée})

então, para colocar a “parte inferior” de cada barra na parte inferior do SVG, cada altura dos rects tem de ser apenas o próprio valor dos dados:

.attr("height", function(d) { return d; // Juste la valeur de la donnée});

Escalar a partir do fundo

Escalar um pouco, alterando d para d * 4. (Nota: Mais tarde aprenderemos mais sobre as escalas D3, que oferecem melhores formas de realizar isto.)

Crescente a partir do fundop>Aqui está o código do nosso gráfico onde as nossas barras crescem a partir do fundo.

Cores

Adicionar uma cor é fácil. Basta usar attr() para definir um preenchimento:

.attr("fill", "teal");

Teal corresponde à cor chamada teal

Barras de teal

Aqui está um gráfico de barras só de teal. Mas, muitas vezes, deseja-se ajustar a cor da forma para reflectir uma das qualidades dos dados. Isso significa que vai querer programar os dados em cor. (Para o nosso gráfico, isto resulta numa dupla programação, na qual o mesmo valor de dados é programado em duas propriedades visuais: altura e cor.)

Usar dados para definir uma cor é como escrever uma função que também faz referência a d. Aqui substituímos “teal” por uma função personalizada:

.attr("fill", function(d) { return "rgb(0, 0, " + (d * 10) + ")";});

Barres bleues pilotées par des donnéesBarras azuis com dados

Aqui está o código. Não é uma codificação visual particularmente útil, mas pelo menos tem uma ideia de como traduzir os dados em cor. Aqui, d é multiplicado por 10, e depois é usado no valor de azul numa definição de cor rgb(). Quanto maior for o valor de d (barras maiores), mais azulada será a barra. Para valores menores de d (barras menores) as barras serão menos azuis (mais próximas do preto).

Rótulos (ou rótulos)

Visuais são óptimos, mas por vezes será necessário exibir os valores dos dados em texto na sua visualização. É aí que entram as etiquetas de valor, e são realmente, realmente fáceis de gerar com D3.

Lembra-se da introdução ao SVG: pode adicionar elementos de texto ao elemento SVG. Vamos começar com:

svg.selectAll("text") .data(dataset) .enter() .append("text")

Sons familiares? Tal como fizemos para os recitais, estamos a fazer o mesmo para os textos. Primeiro, seleccione o que pretende, introduza os dados, adicione os novos elementos com enter() (que neste momento são apenas os titulares dos lugares), e finalmente adicione os novos elementos de texto ao DOM.

P>Vamos completar este código para incluir o valor dos dados em cada elemento de texto usando o texto()

.text(function(d) { return d; })

e definir os valores x e y para posicionar o texto. É mais fácil se eu apenas copiar/colar o mesmo código que usamos acima para as barras:

.attr("x", function(d, i) { return i * (w / dataset.length); }) .attr("y", function(d) { return h - (d * 4); });

Bébés étiquettes !Labéis bebés!”

Aha! Etiquetas! Mas alguns estão cortados no topo. Vamos tentar movê-los para baixo, dentro das barras, adicionando alguns pixels a x e y:

.attr("x", function(d, i) { return i * (w / dataset.length) + 5; // +5 }) .attr("y", function(d) { return h - (d * 4) + 15; // +15 });

Labels in bars

Bem melhor, mas não legível. Felizmente, podemos corrigir isso:

.attr("font-family", "sans-serif") .attr("font-size", "11px") .attr("fill", "white");

Etiquetas muito boas

Código fantasti! Se não é uma aberração da tipografia, então é suficiente. Se, por outro lado, for como eu, notará que as etiquetas não estão perfeitamente alinhadas na sua barra. É bastante fácil de corrigir isso. Vamos utilizar o atributo SVG para centrar o texto na horizontal em relação a x:

.attr("text-anchor", "middle")

Next, vamos mudar a forma como calculamos a posição x definindo-a como o lado esquerdo de cada barra mais metade da largura da barra:

.attr("x", function(d, i) { return i * (w / dataset.length) + (w / dataset.length - barPadding) / 2; })

Vamos também editar as etiquetas por um pixel para um espaçamento perfeito:

.attr("y", function(d) { return h - (d * 4) + 14; // 15 vaut est maintenant 14 })

Etiquetas centradas

Terminado! Agora vamos afastar-nos dos gráficos de barras por um pouco.

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *