Spec-Zone.ru › D3.js 3

Выборки

Справочник API ▸ Основной модуль ▸ Выборки

Выборка — это массив элементов, извлечённых из текущего документа. D3 использует CSS3 для выбора элементов. Например, вы можете выбрать элементы по тегу ("div"), классу (".awesome"), уникальному идентификатору ("#foo"), атрибуту ("[color=red]") или по содержанию ("родитель дочерний элемент"). Выборки могут быть пересечены (".this.that" для логического И) или объединены (".this, .that" для логического ИЛИ). Если ваш браузер не поддерживает селекторы напрямую, вы можете включить Sizzle перед D3 для обеспечения обратной совместимости.

После выбора элементов вы применяете к ним операторы для выполнения действий. Эти операторы могут получать или устанавливать атрибуты, стили, свойства, HTML и текстовое содержимое. Значения атрибутов и т.п. задаются как константы или функции; последние вычисляются для каждого элемента. Вы также можете объединить выборки с данными; эти данные доступны операторам для трансформаций, основанных на данных. Кроме того, объединение с данными создаёт подвыборки enter и exit, чтобы вы могли добавлять или удалять элементы в ответ на изменения данных.

Обычно вам не придётся использовать for циклы или рекурсивные функции для изменения документа с помощью D3. Это потому, что вы работаете с целыми выборками сразу, а не итерируете по отдельным элементам. Однако вы по-прежнему можете вручную итерировать по элементам, если хотите: существует оператор each, который вызывает произвольную функцию, а выборки являются массивами, поэтому к элементам можно получить доступ напрямую (например, selection[0][0]). D3 поддерживает цепочки методов для краткости при применении нескольких операторов: значение возвращаемого оператором является выборкой.

Выбор элементов

D3 предоставляет два метода верхнего уровня для выбора элементов: select и selectAll. Эти методы принимают строки селекторов; первый выбирает только первый соответствующий элемент, а второй выбирает все соответствующие элементы в порядке обхода документа. Эти методы также могут принимать узлы, что полезно для интеграции с сторонними библиотеками, такими как jQuery, или инструментами разработчика ($0).

d3.select(selector)

Выбирает первый элемент, соответствующий заданной строке селектора, возвращая выборку из одного элемента. Если ни один элемент в текущем документе не соответствует заданному селектору, возвращается пустая выборка. Если несколько элементов соответствуют селектору, будет выбран только первый соответствующий элемент (в порядке обхода документа).

d3.select(node)

Выбирает указанный узел. Это полезно, если у вас уже есть ссылка на узел, например, d3.select(this) внутри обработчика событий или глобальная переменная, такая как document.body. Эта функция не обходит DOM.

d3.selectAll(selector)

Выбирает все элементы, соответствующие заданному селектору. Элементы будут выбраны в порядке обхода документа (сверху вниз). Если ни один элемент в текущем документе не соответствует заданному селектору, возвращается пустая выборка.

d3.selectAll(nodes)

Выбирает указанный массив элементов. Это полезно, если у вас уже есть ссылка на узлы, например, d3.selectAll(this.childNodes) внутри обработчика событий или глобальная переменная, такая как document.links. Аргумент nodes не обязательно должен быть массивом; любой псевдомассив, который можно преобразовать в массив (например, NodeList или arguments), будет работать. Эта функция не обходит DOM.

Работа с выборками

Выборки — это массивы элементов — буквально (возможно, не буквально...). D3 привязывает дополнительные методы к массиву, чтобы вы могли применять операторы к выбранным элементам, например, устанавливать атрибут для всех выбранных элементов. Один нюанс заключается в том, что выборки группируются: вместо одномерного массива каждая выборка является массивом массивов элементов. Это сохраняет иерархическую структуру подвыборок. В большинстве случаев вы можете игнорировать эту деталь, но именно поэтому выборка из одного элемента выглядит как [�[node]�] , а не как [node]. Более подробную информацию о вложенных выборках см. в Вложенные выборки.

Если вы хотите узнать, как работают выборки, попробуйте выбрать элементы интерактивно, используя консоль разработчика вашего браузера. Вы можете проверить возвращаемый массив, чтобы увидеть, какие элементы были выбраны и как они сгруппированы. Затем вы можете применить операторы к выбранным элементам и увидеть, как изменится содержимое страницы.

Содержимое

D3 имеет множество операторов, влияющих на содержимое документа. Именно их вы будете использовать чаще всего для отображения данных! При использовании для установки содержимого документа операторы возвращают текущую выборку, поэтому вы можете объединить несколько операторов в одном компактном выражении.

selection.attr(name[, value])

Если value указан, устанавливает атрибут с указанным именем в указанное значение для всех выбранных элементов. Если value — константа, то всем элементам присваивается одинаковое значение атрибута; в противном случае, если value — функция, то функция вычисляется для каждого выбранного элемента (в порядке), получая в качестве аргументов текущий элемент данных d и текущий индекс i, с контекстом this как текущий элемент DOM. Возвращаемое значение функции используется для установки атрибута каждого элемента. Значение null удалит указанный атрибут.

Если value не указан, возвращает значение указанного атрибута для первого не-null элемента в выборке. Это обычно полезно только в том случае, если вы знаете, что выборка содержит ровно один элемент.

Указанное имя может иметь префикс пространства имён, такой как xlink:href, чтобы указать атрибут «href» в пространстве имён XLink. По умолчанию D3 поддерживает пространства имён svg, xhtml, xlink, xml и xmlns. Дополнительные пространства имён можно зарегистрировать, добавив их в d3.ns.prefix с помощью записи в точечной нотации.

имя также может быть объектом с атрибутами имя и значение.

selection.classed(name[, value])

Этот оператор — вспомогательная функция для установки атрибута «class»; он понимает, что атрибут «class» представляет собой набор токенов, разделённых пробелами. Под капотом он будет использовать classList, если доступен, для удобного добавления, удаления и переключения CSS-классов.

Если value указан, устанавливает, присутствует ли указанный класс у выбранных элементов. Если value — константа, и она имеет истинное значение, то всем элементам назначается указанный класс, если он ещё не назначен; если ложное значение, то класс удаляется из всех выбранных элементов, если он был назначен. Если value — функция, то она вычисляется для каждого выбранного элемента (в порядке), получая в качестве аргументов текущий элемент данных d и текущий индекс i, с контекстом this как текущий элемент DOM. Возвращаемое значение функции используется для назначения или удаления указанного класса для каждого элемента.

Если вы хотите установить сразу несколько классов, используйте литерал объекта, например: selection.classed({'foo': true, 'bar': false}), или используйте список имён классов, разделённых пробелами, например: selection.classed('foo bar', true).

Если value не указан, возвращает true тогда и только тогда, когда у первого не-null элемента в этой выборке есть указанный класс. Это обычно полезно только в том случае, если вы знаете, что выборка содержит ровно один элемент.

selection.style(name[, value[, priority]])

Если value указан, устанавливает свойство CSS-стиля с указанным именем в указанное значение для всех выбранных элементов. Если value — константа, то всем элементам присваивается одинаковое значение стиля; в противном случае, если value — функция, то функция вычисляется для каждого выбранного элемента (в порядке), получая в качестве аргументов текущий элемент данных d и текущий индекс i, с контекстом this как текущий элемент DOM. Возвращаемое значение функции используется для установки свойства стиля каждого элемента. Значение null удалит свойство стиля. Также можно указать необязательный priority, равный null или строке «important» (без восклицательного знака).

Если вы хотите установить несколько свойств стиля сразу, используйте литерал объекта. Например:

selection.style({stroke: "black", "stroke-width": "2px"});

Обратите внимание, что CSS-стили обычно имеют связанные единицы. Например, "3px" — это допустимое значение свойства stroke-width, в то время как 3 — нет. Хотя некоторые браузеры неявно присваивают единицу «px» (пиксел) числовым значениям, не все браузеры это делают: например, IE генерирует ошибку «недопустимые аргументы» и останавливает выполнение!

Если value не указан, возвращает текущее вычисленное значение указанного свойства стиля для первого не-null элемента в выборке. Это обычно полезно только в том случае, если вы знаете, что выборка содержит ровно один элемент. Обратите внимание, что вычисленное значение может отличаться от ранее установленного значения, особенно если свойство стиля было установлено с помощью сокращённого свойства (например, стиль «font», который является сокращением для «font-size», «font-face» и т.д.).

selection.property(name[, value])

Некоторые HTML-элементы имеют специальные свойства, недоступные через стандартные атрибуты или стили. Например, текстовые поля формы имеют свойство value типа string, а флажки — свойство checked типа boolean. Вы можете использовать оператор property для получения или установки этих свойств или любого другого адресуемого поля на базовом элементе, например className.

Если value указан, устанавливает свойство с указанным именем в указанное значение для всех выбранных элементов. Если value — константа, то всем элементам присваивается одинаковое значение свойства; в противном случае, если value — функция, то функция вычисляется для каждого выбранного элемента (в порядке), получая в качестве аргументов текущий элемент данных d и текущий индекс i, с контекстом this как текущий элемент DOM. Возвращаемое значение функции используется для установки свойства каждого элемента. Значение null удалит указанное свойство.

Если вы хотите установить сразу несколько свойств, используйте литерал объекта, например: selection.property({'foo': 'bar', 'baz': 'qux'}).

Если значение не указано, возвращает значение указанного свойства для первого элемента без значения null в выборке. Это обычно полезно только если вы знаете, что выборка содержит ровно один элемент.

selection.text([значение])

Оператор text основан на свойстве textContent; установка текстового содержимого заменит все существующие дочерние элементы.

Если значение указано, устанавливает текстовое содержимое на указанное значение для всех выбранных элементов. Если значение является константой, то всем элементам устанавливается одинаковое текстовое содержимое; в противном случае, если значение является функцией, то функция вычисляется для каждого выбранного элемента (в порядке), получая текущее значение данных d и текущий индекс i, с контекстом this в качестве текущего DOM-элемента. Значение возвращаемое функцией используется для установки текстового содержимого каждого элемента. Значение null очистит содержимое.

Если значение не указано, возвращает текстовое содержимое для первого элемента без значения null в выборке. Это обычно полезно только если вы знаете, что выборка содержит ровно один элемент.

selection.html([значение])

Оператор html основан на свойстве innerHTML; установка содержимого inner HTML заменит все существующие дочерние элементы. Также вы можете использовать операторы append или insert для создания HTML-содержимого с использованием данных; этот оператор предназначен для случаев, когда вам нужно немного HTML-кода, например, для форматирования.

Если значение указано, устанавливает содержимое inner HTML на указанное значение для всех выбранных элементов. Если значение является константой, то всем элементам устанавливается одинаковое содержимое inner HTML; в противном случае, если значение является функцией, то функция вычисляется для каждого выбранного элемента (в порядке), получая текущее значение данных d и текущий индекс i, с контекстом this в качестве текущего DOM-элемента. Значение возвращаемое функцией используется для установки содержимого inner HTML каждого элемента. Значение null очистит содержимое.

Если значение не указано, возвращает содержимое inner HTML для первого элемента без значения null в выборке. Это обычно полезно только если вы знаете, что выборка содержит ровно один элемент.

Примечание: как следует из названия, selection.html поддерживается только для HTML-элементов. SVG-элементы и другие не-HTML-элементы не поддерживают свойство innerHTML и, следовательно, несовместимы с selection.html. Рассмотрите использование XMLSerializer для преобразования поддерева DOM в текст. Также обратите внимание на innersvg polyfill, который предоставляет обход для поддержки свойства innerHTML для SVG-элементов.

selection.append(имя)

Добавляет новый элемент с указанным именем в качестве последнего дочернего элемента каждого элемента в текущей выборке, возвращая новую выборку, содержащую добавленные элементы. Каждый новый элемент наследует данные текущих элементов, если таковые имеются, аналогично select для подвыборок.

Имя может быть указано как константная строка или как функция, возвращающая DOM-элемент для добавления. Если имя является функцией, она получает текущее значение данных d и текущий индекс i, с контекстом this в качестве текущего DOM-элемента. Для добавления произвольного элемента, основанного на связанных данных, он должен быть создан в функции. Например:

selection.enter().append(function(d) {
    return document.createElementNS("http://www.w3.org/2000/svg", d.type)
})

Когда имя указано как строка, оно может иметь префикс пространства имён вида "пространство_имён:тег". Например, "svg:text" создаст элемент "text" в пространстве имён SVG. По умолчанию D3 поддерживает пространства имён svg, xhtml, xlink, xml и xmlns. Дополнительные пространства имён могут быть зарегистрированы путём добавления в d3.ns.prefix. Если пространство имён не указано, оно наследуется от окружающего элемента; или, если имя является одним из известных префиксов, используется соответствующее пространство имён (например, "svg" подразумевает "svg:svg").

selection.insert(имя[, перед])

Вставляет новый элемент с указанным именем перед элементом, соответствующим указанному селектору перед, для каждого элемента в текущей выборке, возвращая новую выборку, содержащую вставленные элементы. Если селектор перед не соответствует никаким элементам, новый элемент будет последним дочерним, как в случае с append. Каждый новый элемент наследует данные текущих элементов (если таковые имеются) аналогично select для подвыборок.

Имя может быть указано как константная строка или как функция, возвращающая DOM-элемент для добавления. Когда имя указано как строка, оно может иметь префикс пространства имён вида "пространство_имён:тег". Например, "svg:text" создаст элемент "text" в пространстве имён SVG. По умолчанию D3 поддерживает пространства имён svg, xhtml, xlink, xml и xmlns. Дополнительные пространства имён могут быть зарегистрированы путём добавления в d3.ns.prefix. Если пространство имён не указано, оно наследуется от окружающего элемента; или, если имя является одним из известных префиксов, используется соответствующее пространство имён (например, "svg" подразумевает "svg:svg").

Аналогично, селектор перед может быть указан как строка селектора или функция, возвращающая DOM-элемент. Например, insert("div", ":first-child") добавит дочерние div-узлы к текущей выборке. Для выборок enter селектор перед может быть опущен, в этом случае входящие элементы вставляются непосредственно перед следующим по порядку sibling в выборке обновления, если таковой имеется. Это позволяет вставлять элементы в DOM в порядке, соответствующем привязанным данным. Однако, возможно, всё равно потребуется медленная операция selection.order, если обновление элементов меняет порядок.

selection.remove()

Удаляет элементы текущей выборки из текущего документа. Возвращает текущую выборку (те же элементы, что и были удалены), которые теперь «невидимы», отсоединены от DOM. В настоящее время нет специального API для добавления удалённых элементов обратно в документ; однако вы можете передать функцию в selection.append или selection.insert для повторного добавления элементов.

Данные

selection.data([значения[, ключ]])

Объединяет указанный массив данных с текущей выборкой. Указанные значения - это массив значений данных (например, чисел или объектов), или функция, возвращающая массив значений. Если функция ключ не указана, то первое значение данных в значениях присваивается первому элементу текущей выборки, второе значение - второму выбранному элементу и так далее. Когда данные присваиваются элементу, они сохраняются в свойстве __data__ (определено D3), тем самым делая данные «привязанными», так что они доступны при повторном выборе.

Результат метода data - это выборка update; она представляет выбранные DOM-элементы, которые успешно связаны с указанными элементами данных. Выборка update также содержит ссылку на выборки enter и exit для добавления и удаления узлов в соответствии с данными. Выборки update и enter возвращаются в порядке данных, а выборка exit - в порядке документа на момент запроса выборки. Для более подробной информации см. краткий учебник Thinking With Joins.

Функция ключ key([ d [, i ]]) может быть указана для управления тем, как данные соединяются с элементами (это заменяет поведение по умолчанию по индексу). Функция ключ возвращает строку, которая используется для объединения данных с соответствующим элементом на основе ранее привязанных данных. Например, если каждое значение данных имеет уникальное поле name, объединение может быть указано как .data(data, function(d) { return d.name; })

Функция ключ вызывается дважды во время процесса привязки данных, который происходит в двух фазах.

  1. Функция ключ вычисляется для узлов, чтобы сформировать nodeByKeyValue (ассоциативный массив узлов) с контекстом this в качестве узла, d как член узла __data__ и вторым аргументом i как индекс группы выборки.

  2. Функция ключ вычисляется для каждого элемента массива значения - на этот раз с значениями в качестве контекста this, значения[i] как первым аргументом d и индексом значений i как вторым аргументом - и результаты используются для поиска узлов в коллекции nodeByKeyValue. Если поиск успешен, узел добавляется к выборке update, все узлы, не запрошенные, добавляются к выборке exit. Любые элементы данных, которые не нашли соответствующего узла, используются для формирования выборки enter.

Если функция ключа указана, оператор data также влияет на индекс узлов; этот индекс передаётся как второй аргумент i в аргументы любой функции-оператора. Однако имейте в виду, что существующие DOM-элементы не переупорядочиваются автоматически; используйте sort или order по мере необходимости. Более подробный пример того, как функция ключа влияет на объединение данных, см. в учебнике A Bar Chart, Part 2.

Массив значения определяет данные для каждой группы в выборке. Таким образом, если выборка имеет несколько групп (например, d3.selectAll, за которым следует selection.selectAll), то data должна быть указана как функция, возвращающая массив (предполагая, что вы хотите разные данные для каждой группы). Функция получит текущие данные группы (или undefined) и индекс, с группой в качестве контекста this. Например, вы можете привязать двумерный массив к исходной выборке, а затем привязать содержащиеся внутренние массивы к каждой подвыборке. Функция значения в этом случае является функцией тождества: она вызывается для каждой группы дочерних элементов, получает данные, связанные с родительским элементом, и возвращает этот массив данных.

var matrix = [
  [11975,  5871, 8916, 2868],
  [ 1951, 10048, 2060, 6171],
  [ 8010, 16145, 8090, 8045],
  [ 1013,   990,  940, 6907]
];

var tr = d3.select("body").append("table").selectAll("tr")
    .data(matrix)
  .enter().append("tr");

var td = tr.selectAll("td")
    .data(function(d) { return d; })
  .enter().append("td")
    .text(function(d) { return d; });

Если values не указано, этот метод возвращает массив данных для первой группы в выборке. Длина возвращаемого массива будет соответствовать длине первой группы, а индекс каждого элемента данных в возвращаемом массиве будет соответствовать соответствующему индексу в выборке. Если некоторые элементы в выборке равны null или если у них нет связанных данных, соответствующий элемент в массиве будет undefined.

Примечание: метод data не может быть использован для очистки ранее привязанных данных; используйте selection.datum вместо него.

selection.enter()

Возвращает выборку ввода: узлы-заполнители для каждого элемента данных, для которого не был найден соответствующий существующий элемент DOM в текущей выборке. Этот метод определен только для выборки обновления, которая возвращается оператором data. Кроме того, выборка ввода определяет только операторы append, insert, select и call; вы должны использовать эти операторы для создания вводимых элементов перед изменением любого содержимого. Выборки ввода также поддерживают empty и size.

В качестве простого примера рассмотрим случай, когда существующая выборка пуста, и мы хотим создать новые узлы, соответствующие нашим данным:

d3.select("body").selectAll("div")
    .data([4, 8, 15, 16, 23, 42])
  .enter().append("div")
    .text(function(d) { return d; });

Предполагая, что тело изначально пусто, приведенный код создаст шесть новых элементов DIV, добавит их в тело в порядке, указанном в массиве, и присвоит их текстовое содержимое соответствующему (преобразованному к строке) числу:

<div>4</div>
<div>8</div>
<div>15</div>
<div>16</div>
<div>23</div>
<div>42</div>

Другой способ понять вводимые узлы-заполнители заключается в том, что они являются указателями на родительский узел (в этом примере — тело документа); однако они поддерживают только append и insert. После вставки элементов их индексы будут отражать новые позиции, а не обязательно начинаться с нуля или быть непрерывными.

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

var update_sel = svg.selectAll("circle").data(data)
update_sel.attr(/* operate on old elements only */)
update_sel.enter().append("circle").attr(/* operate on new elements only */)
update_sel.attr(/* operate on old and new elements */)
update_sel.exit().remove() /* complete the enter-update-exit pattern */
selection.exit()

Возвращает выборку выхода: существующие элементы DOM в текущей выборке, для которых не был найден новый элемент данных. Этот метод определен только для выборки обновления, которая возвращается оператором data. Выборка выхода определяет все обычные операторы, хотя, как правило, единственный, который вам нужно использовать, это remove; другие операторы существуют в основном для того, чтобы вы могли определить желаемое переходное действие выхода. Обратите внимание, что оператор exit просто возвращает ссылку на выборку выхода, и от вас зависит удаление новых узлов.

В качестве простого примера рассмотрим обновление шести элементов DIV, созданных в приведенном выше примере для оператора ввода. Здесь мы связываем эти элементы с новым массивом данных с некоторыми новыми и некоторыми старыми элементами:

var div = d3.select("body").selectAll("div")
    .data([1, 2, 4, 8, 16, 32], function(d) { return d; });

Теперь div—результат оператора data—ссылается на обновляемую выборку. Поскольку мы указали функцию ключа, используя идентификационную функцию, и новый массив данных содержит числа [4, 8, 16], которые также существуют в старом массиве данных, эта обновляемая выборка содержит три элемента DIV. Предположим, что мы оставим эти элементы без изменений. Мы можем создать и добавить новые элементы [1, 2, 32] с помощью выборки ввода:

div.enter().append("div")
    .text(function(d) { return d; });

Аналогично, мы можем удалить выходящие элементы [15, 23, 42]:

div.exit().remove();

Теперь тело документа выглядит так:

<div>4</div>
<div>8</div>
<div>16</div>
<div>1</div>
<div>2</div>
<div>32</div>

Обратите внимание, что элементы DOM теперь расположены не по порядку. Однако индекс выборки i (второй аргумент функций-операторов) будет правильно соответствовать новому массиву данных. Например, мы могли бы назначить атрибут индекса:

d3.selectAll("div").attr("index", function(d, i) { return i; });

В результате получится:

<div index="2">4</div>
<div index="3">8</div>
<div index="4">16</div>
<div index="0">1</div>
<div index="1">2</div>
<div index="5">32</div>

Если вы хотите, чтобы порядок обхода документа соответствовал порядку данных выборки, вы можете использовать sort или order.

selection.filter(selector)

Фильтрует выборку, возвращая новую выборку, содержащую только элементы, для которых указанный selector имеет значение true. Selector может быть задан либо как функция, либо как строка селектора, например ".foo". Как и другие операторы, функция получает текущий элемент данных d и индекс i, с контекстом this в качестве текущего элемента DOM. Фильтр должен вызываться только для выборок с привязанными элементами DOM, например, из append или insert. Чтобы привязать элементы только к подмножеству данных, вызовите встроенную функцию массива filter для аргумента data. Как и встроенная функция, фильтр D3 не сохраняет индекс исходной выборки в возвращаемой выборке; он возвращает копию с удаленными элементами. Если вы хотите сохранить индекс, используйте select вместо этого.

Например, чтобы выбрать каждый элемент с нечётным индексом (относительно индекса, начинающегося с нуля):

var odds = selection.select(function(d, i) { return i % 2 === 1 ? this : null; });

Аналогично, с использованием функции фильтра:

var odds = selection.filter(function(d, i) { return i % 2 === 1; });

Или селектор фильтра (обратите внимание, что псевдокласс :nth-child использует индекс, начинающийся с единицы, а не с нуля):

var odds = selection.filter(":nth-child(even)");

Таким образом, вы можете использовать либо select, либо filter для применения операторов к подмножеству элементов.

selection.datum([value])

Получает или устанавливает привязанные данные для каждого выбранного элемента. В отличие от метода selection.data, этот метод не вычисляет объединение (и, следовательно, не вычисляет выборки ввода и выхода). Этот метод реализован на основе selection.property:

d3.selection.prototype.datum = function(value) {
  return arguments.length < 1
      ? this.property("__data__")
      : this.property("__data__", value);
};

Если value задано, устанавливает привязанные данные элемента к заданному значению для всех выбранных элементов. Если value является константой, всем элементам задаются одни и те же данные; в противном случае, если value является функцией, то функция вычисляется для каждого выбранного элемента, принимая предыдущие данные d и текущий индекс i, с контекстом this в качестве текущего элемента DOM. Затем функция используется для установки данных каждого элемента. Значение null удалит привязанные данные. Этот оператор не влияет на индекс.

Если value не указано, возвращает привязанные данные для первого элемента, отличного от null, в выборке. Это, как правило, полезно только в том случае, если вам известно, что выборка содержит ровно один элемент.

Примечание: этот метод ранее назывался "map". Старое имя устарело.

Метод datum полезен для доступа к HTML5 настраиваемым атрибутам данных с помощью D3. Например, заданы следующие элементы:

<ul id="list">
  <li data-username="shawnbot">Shawn Allen</li>
  <li data-username="mbostock">Mike Bostock</li>
</ul>

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

selection.datum(function() { return this.dataset; })

Это затем можно использовать, например, для сортировки элементов по имени пользователя.

selection.sort([comparator])

Сортирует элементы в текущей выборке в соответствии с функцией comparator, а затем повторно вставляет элементы документа для соответствия. Возвращает выборку.

Функция сравнения, по умолчанию d3.ascending, получает два элемента данных a и b для сравнения. Она должна возвращать отрицательное, положительное или нулевое значение. Если отрицательное, то a должно стоять перед b; если положительное, то a должно стоять после b; в противном случае a и b считаются равными, и порядок произволен.

Обратите внимание, что сортировка не гарантирует стабильности; однако она гарантирует, что поведение будет таким же, как у встроенного метода sort вашего браузера для массивов.

selection.order()

Повторно вставляет элементы в документ таким образом, что порядок документа соответствует порядку выборки. Это эквивалентно вызову sort(), если данные уже отсортированы, но намного быстрее.

Анимация и взаимодействие

selection.on(type[, listener[, capture]])

Добавляет или удаляет обработчик событий listener для каждого элемента в текущей выборке для указанного type. Type — это строка имени типа события, например, "click", "mouseover" или "submit". (Любой тип события DOM, поддерживаемый вашим браузером, может быть использован.) Listener хранится путем декорирования выбранных элементов DOM с использованием соглашения об именовании "__ontype". Указанный listener вызывается так же, как и другие функции-операторы, принимая текущий элемент данных d и индекс i, с контекстом this в качестве текущего элемента DOM. Для доступа к текущему событию в обработчике событий используйте глобальный d3.event. Возвращаемое значение обработчика событий игнорируется.

Если для выбранного элемента уже был зарегистрирован обработчик событий для того же типа, существующий обработчик удаляется перед добавлением нового обработчика. Для регистрации нескольких обработчиков событий для одного и того же типа событий можно использовать тип, за которым следует необязательный префикс, например, "click.foo" и "click.bar". Первая часть type ("click", например) используется для регистрации обработчика событий (с помощью element.addEventListener()) и методы добавляются к выбранным элементам как __onclick.foo и __onclick.bar. Чтобы удалить обработчик, передайте null в качестве listener. Чтобы удалить все обработчики для определённого типа событий, передайте null в качестве listener, и .type в качестве type, например, selection.on(".foo", null).

Необязательный флаг capture может быть указан, что соответствует значению useCapture W3C флага: "После начала захвата все события указанного типа будут переданы зарегистрированному EventListener до передачи их любому EventTarget ниже его в дереве. События, которые поднимаются вверх по дереву, не будут вызывать EventListener, обозначенный для использования захвата."

Если listener не указан, возвращается текущий обработчик для указанного type, если таковой есть.

Обратите внимание, что, хотя слушатели всегда будут видеть последнюю запись (d) для своего элемента, индекс (i) — это свойство выбора и определяется при создании выбора. Обновление индекса требует повторного выбора и повторной привязки слушателей.

d3.event

Хранит текущее событие, если оно есть. Эта глобальная переменная регистрируется во время обратного вызова обработчика событий с оператором on. Текущее событие сбрасывается после уведомления слушателя в блоке finally. Это позволяет функции слушателя иметь ту же форму, что и другие функции операторов, получая текущую запись d и индекс i.

Объект d3.event является событием DOM и реализует стандартные поля событий, такие как timeStamp и keyCode, а также методы, такие как preventDefault() и stopPropagation(). Хотя вы можете использовать системные свойства события, такие как pageX и pageY, часто удобнее преобразовать положение события в локальную систему координат контейнера, получившего событие. Например, если вы встраиваете SVG в обычный поток вашей страницы, вы можете захотеть получить положение события относительно левого верхнего угла изображения SVG. Если ваш SVG содержит преобразования, вы также можете узнать положение события относительно этих преобразований. Используйте оператор d3.mouse для стандартного курсора мыши и d3.touches для событий многосенсорного ввода на iOS.

d3.mouse(container)

Возвращает координаты x и y текущего d3.event, отнесённые к указанному контейнеру. Контейнер может быть элементом HTML или SVG-контейнера, например, svg:g или svg:svg. Координаты возвращаются в виде массива из двух элементов [x, y].

d3.touch(container[, touches], identifier)

Возвращает координаты x и y касания с заданным идентификатором, связанного с текущим d3.event, относительно указанного контейнера. Если touches не указан, используется свойство текущего события changedTouches. Контейнер может быть элементом HTML или SVG-контейнера, например, svg:g или svg:svg. Координаты возвращаются как массив двухэлементных массивов [ [ x1, y1], [ x2, y2], … ]. Если касания с заданным идентификатором нет в touches, возвращается null; это может быть полезно для игнорирования событий touchmove, когда перемещаются только некоторые касания.

d3.touches(container[, touches])

Возвращает координаты x и y каждого касания, связанного с текущим d3.event, на основе свойства touches, относительно указанного контейнера. Контейнер может быть элементом HTML или SVG-контейнера, например, svg:g или svg:svg. Координаты возвращаются в виде массива двухэлементных массивов [ [ x1, y1], [ x2, y2], … ]. Если touches указан, возвращает позиции указанных касаний; если touches не указан, он используется по умолчанию из свойства touches текущего события.

selection.transition([name])

Запускает переход для текущего выбора. Переходы ведут себя как выборы, за исключением того, что операторы плавно анимируются со временем, а не применяются мгновенно.

Переходы с одинаковым именем являются исключительными на элемент. Когда новый переход запускается на элементе, он прерывает любой активный переход с тем же именем на этом элементе. Если name не указан, используется пустое имя (“”). Обратите внимание, что переходы с нулевой задержкой не запускаются до следующего тика таймера, что обычно происходит примерно через 17 мс после планирования.

selection.interrupt([name])

Немедленно прерывает активный переход с указанным name для выбранных элементов, если он есть. Если name не указан, используется пустое имя (“”). Не отменяет запланированные переходы, которые еще не начались. Чтобы отменить запланированные переходы, просто создайте новый переход с нулевой задержкой после прерывания текущего перехода:

selection
    .interrupt() // cancel the current transition
    .transition(); // preempt any scheduled transitions

Подвыборки

В то время как методы выбора верхнего уровня запрашивают всю документацию, операторы select и selectAll выбора ограничивают запросы потомками каждого выбранного элемента; мы называем это "подвыборкой". Например, d3.selectAll("p").select("b") возвращает первый жирный ("b") элемент в каждом абзаце ("p"). Подвыборка через selectAll группирует элементы по предку. Таким образом, d3.selectAll("p").selectAll("b") группирует по абзацам, а d3.selectAll("p b") возвращает плоский выбор. Подвыборка через select похожа, но сохраняет группы и распространяет данные. Группировка играет важную роль в объединении данных, и функциональные операторы могут зависеть от числового индекса текущего элемента в его группе.

selection.select(selector)

Для каждого элемента в текущем выборе выбирается первый дочерний элемент, который соответствует заданной строке selector. Если ни один элемент не соответствует указанному селектору для текущего элемента, элемент с текущим индексом будет null в возвращаемом выборе; операторы (за исключением data) автоматически пропускают нулевые элементы, сохраняя тем самым индекс существующего выбора. Если текущий элемент имеет связанные данные, эти данные наследуются подвыборкой и автоматически привязываются к новым выбранным элементам. Если несколько элементов соответствуют селектору, будет выбран только первый соответствующий элемент в порядке обхода документа.

Селектор также может быть задан как функция, возвращающая элемент или null, если соответствующего элемента нет. В этом случае указанный селектор вызывается так же, как и другие функции операторов, получая текущую запись d и индекс i, с контекстом this в качестве текущего DOM-элемента.

selection.selectAll(selector)

Для каждого элемента в текущем выборе выбираются дочерние элементы, которые соответствуют заданной строке selector. Возвращаемый выбор группируется по узлу предка в текущем выборе. Если ни один элемент не соответствует указанному селектору для текущего элемента, группа с текущим индексом будет пустой в возвращаемом выборе. Подвыборка не наследует данные от текущего выбора; однако, если значение data задано как функция, эта функция будет вызываться с данными d узла предка и индексом группы i для определения привязок данных к подвыборке.

Группировка с помощью selectAll также влияет на последующие входящие плацехолдеры узлов. Таким образом, чтобы указать родительский узел при добавлении входящих узлов, используйте select, за которым следует selectAll:

d3.select("body").selectAll("div")

Вы можете увидеть родительский узел каждой группы, проверив свойство parentNode каждого массива группы, например selection[0].parentNode.

Селектор также может быть задан как функция, возвращающая массив элементов (или NodeList), или пустой массив, если соответствующих элементов нет. В этом случае указанный селектор вызывается так же, как и другие функции операторов, получая текущую запись d и индекс i, с контекстом this в качестве текущего DOM-элемента.

Управление

Для расширенного использования D3 имеет несколько дополнительных операторов для управления потоком.

selection.each(function)

Вызывает указанную функцию для каждого элемента в текущем выборе, передавая текущую запись d и индекс i, с контекстом this текущего DOM-элемента. Этот оператор используется почти всеми другими операторами и может использоваться для вызова произвольного кода для каждого выбранного элемента. Оператор each может использоваться для обработки выборок рекурсивно, используя d3.select(this) внутри функции обратного вызова.

selection.call(function[, arguments…])

Вызывает указанную функцию один раз, передавая текущий выбор вместе с любыми необязательными аргументами. Оператор call всегда возвращает текущий выбор, независимо от возвращаемого значения указанной функции. Оператор call идентичен вызову функции вручную; но он делает проще использование цепочки методов. Например, предположим, что мы хотим установить несколько атрибутов одинаковым способом в разных местах. Поэтому мы берем код и заключаем его в повторно используемую функцию:

function foo(selection) {
  selection
      .attr("name1", "value1")
      .attr("name2", "value2");
}

Теперь мы можем сказать это:

foo(d3.selectAll("div"));

Или, эквивалентно:

d3.selectAll("div").call(foo);

Контекст this вызываемой функции также является текущим выбором. Это немного избыточно с первым аргументом, который мы, возможно, исправим в будущем.

Если вы используете метод объекта в selection.call и вам нужен this для указания этого объекта, создайте функцию, связанную с объектом, прежде чем вызывать.

function Foo(text) {
    this.text = text;
}

Foo.prototype.setText = function(selection) {
    selection.text(this.text);
}

var bar = new Foo("Bar");

d3.selectAll("span").call(bar.setText.bind(bar));
// Or
d3.selectAll("span").call(Foo.prototype.setText.bind(bar));
selection.empty()

Возвращает true, если текущий выбор пуст; выбор пуст, если он не содержит элементов или содержит только нулевые элементы.

selection.node()

Возвращает первый ненулевой элемент в текущем выборе. Если выбор пуст, возвращает null.

selection.size()

Возвращает общее количество элементов в текущем выборе.

Расширение

d3.selection()

Возвращает корневой выбор, эквивалентный d3.select(document.documentElement). Эта функция также может использоваться для проверки, является ли объект выбором: o instanceof d3.selection. Вы также можете добавлять новые методы к прототипу выбора. Например, для добавления удобного метода для установки свойства "checked" для чекбоксов, вы можете сказать:

d3.selection.prototype.checked = function(value) {
  return arguments.length < 1
      ? this.property("checked")
      : this.property("checked", value);
};

© 2010–2016 Michael Bostock
Licensed under the BSD License.
https://github.com/d3/d3-3.x-api-reference/blob/master/Selections.md

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API