Выборки (selections) — центральная концепция библиотеки D3.js. Практически любая операция в D3 строится вокруг выборки: получение элементов DOM, изменение атрибутов, работа с данными, анимации, обработка событий и создание визуализаций.
Выборка представляет собой объект, содержащий один или несколько DOM-элементов, к которым затем применяются операции D3.
Основная идея заключается в декларативном управлении документом: вместо ручного обхода DOM библиотека позволяет описывать, что именно должно измениться.
d3.select()Метод select() выбирает первый элемент, соответствующий
CSS-селектору.
d3.select("body")
Выбор элемента по классу:
d3.select(".container")
Выбор элемента по идентификатору:
d3.select("#chart")
После выбора можно выполнять операции:
d3.select("#title")
.text("D3.js Selections")
В данном примере:
id="title"text()d3.selectAll()Для работы с набором элементов используется
selectAll().
d3.selectAll("p")
Теперь выборка содержит все элементы <p>.
Пример изменения стилей:
d3.selectAll("p")
.style("color", "blue")
Все абзацы станут синими.
Объект selection не является обычным массивом. Это специальная структура D3, содержащая:
Пример:
const selection = d3.selectAll("div")
Объект selection хранит внутренние структуры, которыми
управляет D3.
D3 активно использует chaining — цепочки вызовов методов.
d3.select("#box")
.style("width", "200px")
.style("height", "200px")
.style("background", "steelblue")
Каждый метод возвращает объект selection, позволяя продолжать цепочку.
Преимущества:
text()Изменяет текстовое содержимое.
d3.select("#message")
.text("Hello D3")
Получение текста:
const text = d3.select("#message").text()
html()Позволяет вставлять HTML.
d3.select("#content")
.html("<strong>Bold text</strong>")
Следует учитывать риск XSS при работе с пользовательскими данными.
attr()Используется для изменения HTML- и SVG-атрибутов.
d3.select("img")
.attr("src", "image.png")
Пример для SVG:
d3.select("circle")
.attr("cx", 100)
.attr("cy", 50)
.attr("r", 40)
Получение значения:
const radius = d3.select("circle").attr("r")
style()Изменяет CSS-свойства.
d3.select("#panel")
.style("background-color", "lightgray")
Несколько стилей:
d3.select("#panel")
.style("padding", "20px")
.style("border", "1px solid black")
Получение значения:
const color = d3.select("#panel")
.style("background-color")
classed()Добавляет или удаляет классы.
Добавление класса:
d3.select("#item")
.classed("active", true)
Удаление:
d3.select("#item")
.classed("active", false)
Проверка:
const isActive = d3.select("#item")
.classed("active")
append()Создаёт новый дочерний элемент.
d3.select("body")
.append("p")
.text("New paragraph")
Создание SVG:
const svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 300)
Добавление круга:
svg.append("circle")
.attr("cx", 100)
.attr("cy", 100)
.attr("r", 50)
ins ert()Позволяет вставить элемент перед другим.
d3.select("body")
.insert("p", ":first-child")
.text("Inserted paragraph")
remove()Удаляет элементы из DOM.
d3.select("#old")
.remove()
Удаление группы элементов:
d3.selectAll(".unused")
.remove()
Выборки могут быть вложенными.
d3.select("#container")
.selectAll("p")
Сначала выбирается контейнер, затем все абзацы внутри него.
D3 сохраняет контекст родительских элементов.
Пример:
d3.selectAll(".card")
.select("h2")
Для каждого .card будет найден свой h2.
Это важное отличие от обычного DOM API.
each()Позволяет выполнить функцию для каждого элемента.
d3.selectAll("li")
.each(function(d, i) {
console.log(i)
})
Параметры:
d — данныеi — индексthis внутри функции указывает на DOM-элемент.
node()Возвращает первый DOM-элемент выборки.
const node = d3.select("#chart").node()
nodes()Возвращает массив элементов.
const nodes = d3.selectAll("div").nodes()
empty()const isEmpty = d3.select(".missing").empty()
Возвращает true, если элемент не найден.
size()const count = d3.selectAll("p").size()
filter()Фильтрация по условию:
d3.selectAll("p")
.filter(function(d, i) {
return i % 2 === 0
})
.style("color", "red")
Красными станут только чётные элементы.
sort()d3.selectAll("div")
.sort((a, b) => a.val ue - b.value)
Используется совместно с привязанными данными.
merge()Часто применяется после enter().
enterSelection.merge(updateSelection)
Позволяет объединить новые и существующие элементы.
Одна из ключевых особенностей D3 — связывание данных с DOM.
const data = [10, 20, 30]
d3.select("body")
.selectAll("p")
.data(data)
Теперь каждый элемент связан со значением массива.
data()Пример:
d3.select("body")
.selectAll("p")
.data([1, 2, 3])
.text(d => d)
d — текущее значение данных.
Если данных больше, чем элементов DOM, используется enter-selection.
const data = [1, 2, 3]
d3.select("body")
.selectAll("p")
.data(data)
.enter()
.append("p")
.text(d => d)
Процесс:
<p>append() создаются новые узлыЕсли элемент уже существует, D3 обновляет его.
d3.selectAll("p")
.data([5, 10, 15])
.text(d => d)
Если элементов больше, чем данных:
d3.selectAll("p")
.data([1])
.exit()
.remove()
Лишние элементы удаляются.
const data = [10, 20, 30]
const selection = d3.select("body")
.selectAll("p")
.data(data)
selection.enter()
.append("p")
.merge(selection)
.text(d => d)
selection.exit().remove()
Этот механизм является фундаментом динамических визуализаций.
D3 позволяет указывать ключ для сопоставления элементов.
.data(data, d => d.id)
Ключи особенно важны:
Без ключей D3 использует индекс массива.
Во многих методах используется this.
d3.selectAll("button")
.each(function() {
d3.select(this)
.style("color", "red")
})
this — текущий DOM-элемент.
d3.selectAll("button")
.on("click", function() {
d3.select(this)
.classed("active", true)
})
on()d3.select("#btn")
.on("click", function(event) {
console.log(event)
})
Поддерживаются любые DOM-события:
Большинство методов D3 могут принимать функцию.
d3.selectAll("p")
.style("font-size", (d, i) => `${i * 2 + 12}px`)
D3 автоматически вызывает функцию для каждого элемента.
Стандартный набор:
function(d, i, nodes)
Где:
d — данныеi — индексnodes — массив элементовПрактически любой график в D3 строится через выборки.
Пример столбчатой диаграммы:
const data = [30, 80, 45, 60]
d3.select("svg")
.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", (d, i) => i * 60)
.attr("y", d => 200 - d)
.attr("width", 50)
.attr("height", d => d)
Многие операции возвращают новую выборку.
const divs = d3.selectAll("div")
const filtered = divs.filter(".active")
filtered — новая выборка.
D3 internally хранит элементы в группах.
Например:
d3.selectAll(".row")
.selectAll(".cell")
Каждая группа .cell относится к своему
.row.
Это позволяет строить сложные иерархические структуры.
Выборки особенно важны при работе с SVG.
const svg = d3.select("svg")
svg.append("line")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", 100)
.attr("y2", 100)
D3 одинаково работает:
call()Позволяет передать selection в функцию.
function highlight(selection) {
selection.style("border", "2px solid red")
}
d3.selectAll(".box")
.call(highlight)
Полезно для повторного использования логики.
Многие методы D3 работают в двух режимах.
Setter:
selection.attr("width", 500)
Getter:
selection.attr("width")
Поведение зависит от количества аргументов.
Анимации D3 строятся поверх выборок.
d3.select("circle")
.transition()
.duration(1000)
.attr("r", 100)
transition() создаёт специальную
transition-selection.
Наиболее распространённый шаблон:
d3.select(container)
.selectAll(elements)
.data(data)
.join(elementType)
join()Современный API D3 упрощает enter-update-exit.
d3.select("svg")
.selectAll("circle")
.data(data)
.join("circle")
D3 автоматически:
join()selection.join(
enter => enter.append("circle"),
update => update,
exit => exit.remove()
)
Позволяет управлять всеми стадиями жизненного цикла.
Основные рекомендации:
data()Плохо:
d3.select("#chart")
d3.select("#chart")
d3.select("#chart")
Лучше:
const chart = d3.select("#chart")
exit()Без удаления старых элементов DOM начинает разрастаться.
thisСтрелочные функции не создают собственный this.
Проблема:
.on("click", () => {
d3.select(this)
})
Корректно:
.on("click", function() {
d3.select(this)
})
D3 описывает состояние интерфейса через данные.
Главная идея:
данные → выборка → DOM
DOM становится отражением структуры данных.
Именно концепция selection делает возможными: