Методы d3.select() и d3.selectAll()
являются основой механизма работы с DOM в библиотеке D3.js. Через них
выполняется выбор элементов документа, последующая привязка данных,
изменение атрибутов, стилей, текста и создание визуализаций.
Оба метода напоминают работу стандартных DOM API
(querySelector и querySelectorAll), однако
возвращают не обычные DOM-узлы, а специальные объекты —
selection.
d3.selectd3.select(selector)
или
d3.select(node)
const svg = d3.select("svg");
В данном случае выбирается первый найденный элемент
<svg>.
Аналог:
document.querySelector("svg");
Однако d3.select() возвращает объект типа
Selection, поддерживающий цепочки методов.
const selection = d3.select("p");
Объект selection содержит:
Пример:
d3.select("p")
.text("Новый текст")
.style("color", "red");
Особенность d3.select():
d3.select(".item")
будет выбран только первый элемент с классом .item.
HTML:
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
Результат:
<div>.Метод принимает не только строку-селектор, но и готовый DOM-элемент.
const element = document.getElementById("box");
d3.select(element)
.style("background", "blue");
d3.selectAlld3.selectAll(selector)
или
d3.selectAll(nodes)
d3.selectAll("li")
Выбираются все элементы <li>.
d3.selectd3.selectd3.select("li")
Выбирает:
только первый li
d3.selectAlld3.selectAll("li")
Выбирает:
все li
d3.selectAll("p")
.style("font-size", "20px");
Стиль применяется ко всем найденным <p>.
Объект selection хранит элементы в виде групп.
Упрощённая схема:
Selection
├── groups
│ ├── [element1, element2, element3]
└── parents
Это важно для:
Методы поддерживают практически любые CSS-селекторы.
d3.select("svg")
d3.select(".chart")
d3.select("#container")
d3.select("div .item")
d3.selectAll("ul li.active")
d3.selectAll("[data-id]")
Одно из главных преимуществ D3 — chaining.
d3.select("h1")
.text("D3.js")
.style("color", "steelblue")
.attr("class", "title");
Каждый метод возвращает selection.
d3.selectconst s = d3.select(".unknown");
Если элемент не найден:
Проверка:
s.empty()
Пример:
if (s.empty()) {
console.log("Элемент не найден");
}
d3.selectAllconst items = d3.selectAll(".missing");
Возвращается пустая selection без ошибок.
.node()Позволяет получить обычный DOM-элемент.
const node = d3.select("svg").node();
Теперь доступны стандартные DOM API.
.nodes()Возвращает массив DOM-элементов.
const nodes = d3.selectAll("p").nodes();
Результат:
[
p,
p,
p
]
.size()Количество выбранных элементов.
const count = d3.selectAll("div").size();
.empty()Проверка пустой selection.
d3.select("canvas").empty()
const container = d3.select("#app");
container.select("p");
Поиск происходит только внутри #app.
d3.selectAll("p")
Поиск по всему документу.
d3.select("#box")
.selectAll("p")
Поиск только внутри #box.
HTML:
<div id="chart">
<p>A</p>
<p>B</p>
</div>
<div id="info">
<p>C</p>
</div>
Jav * aScript:
d3.select("#chart")
.selectAll("p")
.style("color", "red");
Красными станут только:
A
B
Selection не является массивом.
Нельзя:
selection[0]
или
selection.map(...)
const arr = d3.selectAll("div").nodes();
Теперь доступны методы массива:
arr.map(node => node.id);
.each()d3.selectAll("li")
.each(function(d, i) {
console.log(this);
console.log(i);
});
| Аргумент | Значение |
|---|---|
d |
связанные данные |
i |
индекс |
this |
DOM-элемент |
thisВнутри callback:
this === текущий DOM-элемент
Пример:
d3.selectAll("div")
.each(function() {
d3.select(this)
.style("border", "1px solid black");
});
Следует учитывать:
d3.selectAll("div")
.each(() => {
console.log(this);
});
Здесь this не будет ссылаться на DOM-элемент.
Причина — особенности lexical scope у стрелочных функций.
select и selectAll тесно связаны с
механизмом data binding.
const data = [10, 20, 30];
d3.selectAll("p")
.data(data)
.text(d => d);
Каждый <p> получает своё значение.
selectd3.select("p").data([100]);
Связывается только один элемент.
selectAlld3.selectAll("p").data([1,2,3]);
Связывается множество элементов.
d3.select("body")
.selectAll("p")
.data(data)
.enter()
.append("p")
.text(d => d);
Эта конструкция является одной из ключевых в D3.
selectAll перед .data()Часто используется пустая выборка:
d3.select("svg")
.selectAll("circle")
Даже если <circle> ещё нет.
Это необходимо для механизма:
Многие методы D3 возвращают новую selection.
Пример:
const svg = d3.select("svg");
const circles = svg.selectAll("circle");
svg и circles — разные selection.
d3.selectAll("g")
.selectAll("circle")
D3 сохраняет структуру групп.
Упрощённо:
Group 1 -> circles
Group 2 -> circles
Group 3 -> circles
Это важно для:
Наиболее часто методы используются с SVG.
const svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 300);
svg.selectAll("circle")
.data([30, 60, 90])
.enter()
.append("circle")
.attr("cx", d => d)
.attr("cy", 100)
.attr("r", 20);
D3 работает не только с SVG.
d3.selectAll("div")
.style("padding", "10px");
Допустимо комбинировать подходы.
const button = document.querySelector("button");
d3.select(button)
.text("Нажато");
selectAlld3.selectAll("*")
может быть дорогостоящей операцией.
Особенно при:
d3.selectAll("div")
внутри каждого кадра анимации.
const divs = d3.selectAll("div");
function update() {
divs.style("opacity", 0.5);
}
D3 сохраняет порядок элементов DOM.
d3.selectAll("li")
вернёт элементы в порядке документа.
.filter()Фильтрация selection.
d3.selectAll("p")
.filter((d, i) => i % 2 === 0)
.style("color", "red");
.select()
внутри selectiond3.selectAll("div")
.select("p")
Для каждого div выбирается только первый
p.
.selectAll() внутри selectiond3.selectAll("div")
.selectAll("p")
Выбираются все <p> внутри каждого
div.
.select()Сохраняет структуру групп.
.selectAll()Создаёт новые подгруппы.
Это критически важно при работе с данными.
HTML:
<div>
<p>1</p>
<p>2</p>
</div>
<div>
<p>3</p>
</div>
Jav * aScript:
d3.selectAll("div")
.selectAll("p")
Внутренне:
[
[p, p],
[p]
]
После выборки можно назначать обработчики.
d3.selectAll("button")
.on("click", function() {
d3.select(this)
.style("background", "orange");
});
d3.selectAll(".temp")
.remove();
d3.select("body")
.append("div")
.text("Новый блок");
Неправильно:
d3.selectAll("p")[0]
select и selectAllНеправильно:
d3.select(".item")
если требуется обработать все элементы.
this со стрелочными функциямиНеправильно:
.on("click", () => {
d3.select(this)
})
<ul id="list"></ul>
const data = ["JavaScript", "D3", "SVG"];
d3.select("#list")
.selectAll("li")
.data(data)
.enter()
.append("li")
.text(d => d);
<ul id="list">
<li>JavaScript</li>
<li>D3</li>
<li>SVG</li>
</ul>
$(".item")
Возвращает jQuery-коллекцию.
d3.selectAll(".item")
Возвращает selection с поддержкой data binding.
Без selectAll() невозможен классический цикл обновления
D3.
const circles = svg
.selectAll("circle")
.data(data);
Далее:
circles.enter()
circles.exit()
.join()Начиная с новых версий D3 часто используется:
svg.selectAll("circle")
.data(data)
.join("circle")
Однако основа всё равно строится на selectAll().
d3.selectИспользует:
querySelector()
d3.selectAllИспользует:
querySelectorAll()
После чего D3 оборачивает результат в собственную abstraction layer.
select() и selectAll() — не просто способы
поиска элементов.
Они формируют: