Вопрос

Мне нужно создать классическую демографическую пирамиду с помощью D3.js.Что-то похожее на это изображение:enter image description here

Я нашел несколько примеров, которые выглядят действительно хорошо (этот и этот), но они более сложны, чем я ищу.Кто-нибудь знает хороший ПРОСТОЙ пример, на который я могу посмотреть?Есть какой-нибудь совет, как начать это делать?Должен ли я просто построить две гистограммы рядом друг с другом, по одной для каждой половой группы?

Это было полезно?

Решение

Ключ к созданию такой визуализации — потратить достаточно времени на предварительную настройку макета, прежде чем вы приступите к рисованию.

Есть несколько ключевых измерений, которые вы захотите использовать, чтобы значительно облегчить себе жизнь, когда придет время создавать шкалы и оси для вашей диаграммы.Затем вы можете использовать <g> элементы с переводами, чтобы в каждом «разделе» вашей диаграммы можно было работать в локальных координатах.

Цель состоит в том, чтобы создать две зеркальные области, подобные этой:

two mirrored regions

Это позволит вам использовать одни и те же масштабы для измерений x и y в двух регионах.

Чтобы определить эти области, вы можете сначала установить некоторые значения для полей внутри вашего SVG, а затем создать группу, которая будет находиться внутри этих полей.Это обычная практика в визуализациях d3, и если вы еще с ней не знакомы, сейчас самое время поучиться.Обычно это выглядит примерно так:

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 + ')');

Это хорошая практика, которой следует следовать, поскольку она позволяет вам оставить место в вашем svg-документе для отметок осей, меток и заголовков без необходимости учитывать это пространство при позиционировании частей самой визуализации.Позже, если вы обнаружите, что вам нужно больше места, вы можете просто изменить одно значение в верхней части кода, а не переставлять всю диаграмму.

Другие важные точки — это координаты X двух осей Y.Другими словами, точки, в которых численность населения равна нулю для мужчин и женщин (показаны красными линиями ниже).Это будет заданное расстояние от центральной линии вашей внутренней области (показано синей линией ниже):

middle margin

Вы можете добавить свойство среднего поля к созданному ранее объекту поля, чтобы ссылаться на это значение:

margin.middle = 28;

Вам понадобится создать переменные для хранения положений двух красных линий выше.А пока давайте позвоним им pointA (координата x нулевой линии для мужского населения) и pointB (соответствующая точка для женского населения).

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

var pointA = regionWidth,
    pointB = width - regionWidth;

Как только вы настроите эти точки, все станет намного проще, поскольку вы можете просто подключить эти значения к преобразованию SVG, чтобы перевести создаваемые вами объекты в эти позиции.

Самой сложной частью будут две центральные оси Y, которые имеют один набор меток.Для этого вам нужно хорошо разбираться в том, как d3.svg.axis() создает свои текстовые метки и определяет, какими свойствами можно манипулировать.Для этого нужно знать четыре важных свойства:

  1. axis.orient(direction) указывает направление, в котором указывают галочки, выходящие из оси.В данном случае это будет немного сбивать с толку, поскольку мы хотим, чтобы отметки были направлены к центру, поэтому левая ось будет иметь .orient('right') и правая ось будет иметь .orient('left')

  2. axis.tickSize(inner,outer) устанавливает длину (в единицах SVG) делений, выходящих из оси.«Внешние» метки — это метки на конечных точках оси, их можно установить на 0 в данном случае потому, что мы используем порядковую шкалу с диапазонами диапазонов, поэтому конечные точки не представляют значения.Выберите небольшое значение для внутренних тиков, в этом примере я буду использовать 4.

  3. axis.tickPadding(padding) устанавливает, насколько далеко от конца галочки размещается текстовая привязка текста метки.Мы хотим разместить текстовую привязку в центре изображения, прямо между двумя осями.Поскольку мы уже знаем среднее поле (расстояние от центральной линии до каждой оси) и знаем tickSize (длина делений), мы можем разместить их в центре, взяв разницу этих двух значений: .tickPadding(margin.middle - 4).

  4. axis.tickFormat(format) определяет формат меток делений.Для него можно установить пустую строку, чтобы удалить метки делений с одной из осей, чтобы не происходило перекрытия: .tickFormat('')

Итак, две оси Y можно определить следующим образом:

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('');

Затем, рисуя левую ось Y, выберите ее <text> элементы и установите текстовый якорь как middle поэтому они будут сосредоточены вокруг якоря:

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

ЗДЕСЬ — это простой пример всей диаграммы с использованием некоторых надуманных данных.Я постарался прокомментировать как можно больше общей структуры, чтобы было легче понять.Я также сделал translation(x,y) функция, позволяющая облегчить определение координат x и y каждого перевода, чем при использовании конкатенации строк.Вы можете найти его определение внизу скрипта.

Надеюсь, это поможет. Если у вас возникнут вопросы по поводу деталей, дайте мне знать.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top