d3.js
Выбор
Поиск…
Синтаксис
- d3. выбрать (селектор)
- d3. selectAll (селектор)
- выбор . выбрать (селектор)
- выбор . selectAll (селектор)
- выбор . фильтр (фильтр)
- выбор . слияние (другое)
замечания
Связанные чтения:
Основной выбор и модификации
Если вы знакомы с синтаксисом jQuery и Sizzle, выбор d3 не должен сильно отличаться. d3 имитирует API-переключатели W3C, чтобы упростить взаимодействие с элементами.
В базовом примере выберите все <p>
и добавьте изменения для каждого из них:
d3.selectAll('p')
.attr('class','textClass')
.style('color', 'white');
В двух словах это относительно то же самое, что и в jQuery
$('p')
.attr('class','textClass')
.css('color, 'white')
Как правило, вы начинаете с одного выбора в вашем контейнере div, чтобы добавить элемент SVG, который будет назначен переменной (обычно называемой svg).
var svg = d3.select('#divID').append('svg');
Отсюда мы можем вызвать svg
для выполнения наших подселекций нескольких объектов (даже если они еще не существуют).
svg.selectAll('path')
Различные селекторы
Вы можете выбирать элементы с разными селекторами:
- по тегу:
"div"
- по классу:
".class"
- по id:
"#id"
- по атрибуту:
"[color=blue]"
- множественные селекторы (OR):
"div1, div2, class1"
- множественные селекторы (AND):
"div1 div2 class1"
Простой ограниченный выбор данных
var myData = [
{ name: "test1", value: "ok" },
{ name: "test2", value: "nok" }
]
// We have to select elements (here div.samples)
// and assign data. The second parameter of data() is really important,
// it will determine the "key" to identify part of data (datum) attached to an
// element.
var mySelection = d3.select(document.body).selectAll("div.samples") // <- a selection
.data(myData, function(d){ return d.name; }); // <- data binding
// The "update" state is when a datum of data array has already
// an existing element associated.
mySelection.attr("class", "samples update")
// A datum is in the "enter" state when it's not assigned
// to an existing element (based on the key param of data())
// i.e. new elements in data array with a new key (here "name")
mySelection.enter().append("div")
.attr("class", "samples enter")
.text(function(d){ return d.name; });
// The "exit" state is when the bounded datum of an element
// is not in the data array
// i.e. removal of a row (or modifying "name" attribute)
// if we change "test1" to "test3", "test1" bounded
// element will figure in exit() selection
// "test3" bounded element will be created in the enter() selection
mySelection.exit().attr("class", "samples remove");
Роль заполнителей в настройках «ввода»
Что такое выбор ввода?
В D3.js, когда один связывает данные с элементами DOM, возможны три ситуации:
- Количество элементов и количество точек данных одинаковы;
- Есть больше элементов, чем точек данных;
- Есть больше точек данных, чем элементов;
В ситуации № 3 все точки данных без соответствующего элемента DOM относятся к выбору ввода . Таким образом, в D3.js введите выбор - это выбор, который после присоединения элементов к данным содержит все данные, которые не соответствуют ни одному элементу DOM. Если мы будем использовать функцию append
в выборе ввода , D3 создаст новые элементы, связывающие эти данные для нас.
Это диаграмма Венна, объясняющая возможные ситуации относительно количества точек данных / количества элементов DOM:
Как видим, выбор ввода - это синяя область слева: точки данных без соответствующих элементов DOM.
Структура выбора ввода
Как правило, для ввода введите следующие 4 шага:
-
selectAll
: выбор элементов в DOM; -
data
: подсчитывает и анализирует данные; -
enter
: сравнивая выбор с данными, создайте новые элементы; -
append
: добавьте фактические элементы в DOM;
Это очень простой пример (посмотрите на 4 шага в var divs
):
var data = [40, 80, 150, 160, 230, 260];
var body = d3.select("body");
var divs = body.selectAll("div")
.data(data)
.enter()
.append("div");
divs.style("width", function(d) { return d + "px"; })
.attr("class", "divchart")
.text(function(d) { return d; });
И это результат ( jsfiddle здесь ):
Обратите внимание, что в этом случае мы использовали selectAll("div")
в качестве первой строки в нашей переменной выбора «enter». У нас есть набор данных с 6 значениями, а D3 создал для нас 6 разделов.
Роль заполнителей
Но предположим, что у нас уже есть div в нашем документе, что-то вроде <div>This is my chart</div>
вверху. В этом случае, когда мы пишем:
body.selectAll("div")
мы выбираем существующий div. Таким образом, наш выбор ввода будет иметь только 5 опорных точек без соответствующих элементов. Например, в этом jsfiddle , где уже есть div в HTML («Это моя диаграмма»), это будет результат:
Мы больше не видим значения «40»: наш первый «бар» исчез, и причина в том, что наш «вводный» выбор теперь имеет всего 5 элементов.
Здесь мы должны понимать, что в первой строке нашей переменной выбора ввода selectAll("div")
эти divs являются просто заполнителями . Нам не нужно выбирать все divs
если мы добавляем divs
или весь circle
если мы добавляем circle
. Мы можем выбрать разные вещи. И, если мы не планируем иметь «обновление» или «выход», мы можем выбрать что угодно :
var divs = body.selectAll(".foo")//this class doesn't exist, and never will!
.data(data)
.enter()
.append("div");
Таким образом, мы выбираем все «.foo». Здесь «foo» - это класс, который не только не существует, но и никогда не создается нигде в коде! Но это не имеет значения, это только местозаполнитель. Логика такова:
Если в вашем «вводном» выборе вы выбираете то, что не существует, ваш выбор «войти» всегда будет содержать все ваши данные.
Теперь, выбрав .foo
, наш «ввод» выбор имеет 6 элементов, даже если у нас уже есть div в документе:
И вот соответствующий jsfiddle .
Выбор null
Безусловно, лучший способ гарантировать, что вы ничего не выбираете, - это выбрать null
. Не только это, но и эта альтернатива быстрее, чем любая другая.
Таким образом, для выбора ввода просто выполните:
selection.selectAll(null)
.data(data)
.enter()
.append(element);
Вот демонстрационная скрипта: https://jsfiddle.net/gerardofurtado/th6s160p/
Заключение
Когда вы занимаетесь выбором «войти», проявляйте особую осторожность, чтобы не выбирать то, что уже существует. Вы можете использовать что-либо в своем selectAll
, даже вещи, которые не существуют и никогда не будут существовать (если вы не планируете иметь «обновление» или «выход»).
Код в примерах основан на этом коде Mike Bostock: https://bl.ocks.org/mbostock/7322386
Использование «this» со стрелкой
Большинство функций в D3.js принимают анонимную функцию в качестве аргумента. .attr
примерами являются .attr
, .style
, .text
, .on
и .data
, но список намного больше.
В таких случаях анонимная функция оценивается для каждого выбранного элемента, чтобы:
- Текущая дата (
d
) - Текущий индекс (
i
) - Текущая группа (
nodes
) -
this
как текущий элемент DOM.
В качестве аргументов передаются данные, индекс и текущая группа, известный первый, второй и третий аргументы в D3.js (параметры которого традиционно называются d
, i
и p
в D3 v3.x). Однако для использования this
не нужно использовать никаких аргументов:
.on("mouseover", function(){
d3.select(this);
});
Вышеприведенный код выберет this
когда мышь над элементом. Проверьте, работает ли эта скрипта: https://jsfiddle.net/y5fwgopx/
Функция стрелки
В качестве нового синтаксиса ES6 функция стрелки имеет более короткий синтаксис по сравнению с выражением функции. Тем не менее, для программиста D3, который использует this
постоянно, есть ловушка: функция стрелки не создает свой собственный this
контекст. Это означает, что в функции стрелки this
имеет свое первоначальное значение из охватывающего контекста.
Это может быть полезно при нескольких обстоятельствах, но это проблема для кодера, привыкшего использовать this
в D3. Например, используя тот же пример в приведенной выше скрипте, это не сработает:
.on("mouseover", ()=>{
d3.select(this);
});
Если вы сомневаетесь в этом, вот скрипка: https://jsfiddle.net/tfxLsv9u/
Ну, это не большая проблема: при необходимости можно просто использовать регулярное, старомодное выражение функции. Но что, если вы хотите написать весь свой код с помощью функций стрелок? Возможно ли иметь код со стрелками и по- прежнему использовать this
в D3?
Второй и третий аргументы
Ответ - да , потому что this
то же самое из nodes[i]
. Подсказка действительно присутствует во всем D3 API, когда она описывает это:
... с
this
в качестве текущего элемента DOM (nodes[i]
)
Объяснение простое: поскольку nodes
представляют собой текущую группу элементов в DOM, а i
- индекс каждого элемента, nodes[i]
относятся к текущему самому элементу DOM. То есть, this
.
Поэтому можно использовать:
.on("mouseover", (d, i, nodes) => {
d3.select(nodes[i]);
});
И вот соответствующая скрипка: https://jsfiddle.net/2p2ux38s/