Pergunta

Preciso fazer uma pirâmide populacional de aparência clássica com D3.js.Algo semelhante a esta imagem:enter image description here

Encontrei alguns exemplos que parecem muito bons (esse e esse), mas eles são mais complexos do que procuro.Alguém conhece um bom exemplo SIMPLES que eu possa ver?Algum conselho para começar isso?Devo apenas fazer dois gráficos de barras um ao lado do outro, um para cada grupo sexual?

Foi útil?

Solução

A chave para fazer uma visualização como essa é gastar bastante tempo configurando o layout com antecedência antes de começar a desenhar qualquer coisa.

Existem algumas medidas importantes que você deseja usar para tornar sua vida muito mais fácil quando chegar a hora de fazer as escalas e os eixos do seu gráfico.Então, você pode fazer uso <g> elementos com traduções para que em cada "seção" do seu gráfico você possa trabalhar em coordenadas locais.

O objetivo é criar duas regiões espelhadas como esta:

two mirrored regions

Isso permitirá que você compartilhe as mesmas escalas para as dimensões x e y entre as duas regiões.

Para definir essas regiões, você pode primeiro definir alguns valores para as margens internas do seu svg e, em seguida, criar um grupo para ficar dentro dessas margens.Esta é uma prática comum em visualizações d3 e, se você ainda não estiver familiarizado com ela, é um bom momento para aprender.Geralmente é algo assim:

var width = 400,
    height = 300;

var margin = {
  top: 20,
  right: 10
  bottom: 40,
  left: 10
};

var svg = d3.select('body').append('svg')
  .attr('width', margin.left + width + margin.right)
  .attr('height', margin.top + height + margin.bottom)
  .append('g')
    .attr('class', 'inner-region')
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

Esta é uma boa prática a seguir porque permite que você deixe espaço em seu documento SVG para marcas de eixo, rótulos e títulos, sem ter que levar em conta esse espaço ao posicionar partes da visualização em si.Posteriormente, se achar que precisa de mais espaço, basta ajustar um valor na parte superior do código, em vez de reposicionar todo o diagrama.

Os outros pontos importantes são as coordenadas x dos dois eixos y.Por outras palavras, os pontos em que a população é zero para homens e mulheres (mostrados como linhas vermelhas abaixo).Esta será uma distância definida da linha central da sua região interna (mostrada como uma linha azul abaixo):

middle margin

Você pode adicionar uma propriedade de margem intermediária ao objeto de margem criado anteriormente para fazer referência a este valor:

margin.middle = 28;

Você desejará criar variáveis ​​para armazenar as posições das duas linhas vermelhas acima.Por enquanto, vamos ligar para eles pointA (a coordenada x da linha zero para a população masculina) e pointB (o ponto correspondente para a população feminina).

var regionWidth = (width/2) - margin.middle;

var pointA = regionWidth,
    pointB = width - regionWidth;

Depois de configurar esses pontos, as coisas se tornam muito mais simples, pois você pode simplesmente inserir esses valores em uma transformação SVG para traduzir os objetos criados para essas posições.

A parte mais complicada serão os dois eixos y centrais, que compartilham um único conjunto de rótulos.Para isso, você precisará ter um bom controle sobre como d3.svg.axis() cria seus rótulos de texto e quais propriedades podem ser manipuladas.Existem quatro propriedades importantes que você deve saber para isso:

  1. axis.orient(direction) especifica a direção para a qual as marcas apontam, saindo do eixo.Isso será um pouco confuso neste caso porque queremos que as marcas apontem para o centro, então o eixo esquerdo terá .orient('right') e o eixo direito terá .orient('left')

  2. axis.tickSize(inner,outer) define o comprimento (em unidades SVG) das marcas que saem do eixo.As marcas "externas" são aquelas nas extremidades do eixo e podem ser definidas como 0 neste caso porque estamos usando uma escala ordinal com faixas de intervalo, então os pontos finais não representam valores.Escolha um valor pequeno para os ticks internos, neste exemplo usarei 4.

  3. axis.tickPadding(padding) define a que distância do final da marca de seleção a âncora do texto do rótulo é colocada.Queremos colocar a âncora de texto no centro da imagem, bem entre os dois eixos.Como já conhecemos a margem média (a distância da linha central a cada eixo) e sabemos a tickSize (o comprimento dos ticks), podemos colocá-los no centro calculando a diferença destes dois valores: .tickPadding(margin.middle - 4).

  4. axis.tickFormat(format) especifica o formato dos rótulos de escala.Pode ser definido como uma string vazia para remover rótulos de escala de um dos eixos, para que não ocorra sobreposição: .tickFormat('')

Portanto, os dois eixos y podem ser definidos assim:

var yAxisLeft = d3.svg.axis()
  .scale(yScale)
  .orient('right')
  .tickSize(4,0)
  .tickPadding(margin.middle - 4);

var yAxisRight = d3.svg.axis()
  .scale(yScale)
  .orient('left')
  .tickSize(4,0)
  .tickFormat('');

Então, ao desenhar o eixo y esquerdo, selecione seu <text> elementos e defina a âncora de texto como middle então eles ficarão centralizados na âncora:

.call(yAxisLeft)
  .selectAll('text')
  .style('text-anchor', 'middle');

AQUI é um exemplo simples de um gráfico inteiro usando alguns dados inventados.Tentei comentar o máximo possível da estrutura geral para facilitar o acompanhamento.Eu também fiz um translation(x,y) função para tornar as coordenadas xey de cada tradução mais fáceis de localizar do que seriam ao usar a concatenação de strings.Você pode encontrar sua definição na parte inferior do script.

Espero que isso ajude. Deixe-me saber se você tiver dúvidas sobre os detalhes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top