Метод .filter() используется для отбора элементов из
текущей выборки D3. Он позволяет оставить только те DOM-узлы, которые
удовлетворяют заданному условию. После фильтрации возвращается новая
выборка, содержащая только подходящие элементы.
Синтаксис:
selection.filter(filterFunction)
или
selection.filter(selector)
Метод поддерживает два варианта фильтрации:
.filter()Каждый элемент выборки проходит проверку. Если условие возвращает
true, элемент остаётся в новой выборке. Если
false — исключается.
Пример:
d3.selectAll("circle")
.filter(function() {
return true;
});
В этом случае сохраняются все элементы.
Наиболее гибкий вариант работы.
function(d, i, nodes)
Параметры:
| Параметр | Описание |
|---|---|
d |
Данные, привязанные к элементу |
i |
Индекс элемента |
nodes |
Массив DOM-элементов выборки |
const data = [10, 25, 40, 5, 60];
d3.select("body")
.selectAll("div")
.data(data)
.enter()
.append("div")
.text(d => d)
.filter(d => d > 20)
.style("color", "red");
div..filter(d => d > 20) оставляет только элементы со
значением больше 20.Метод часто применяется для работы с позициями элементов.
d3.selectAll("li")
.filter((d, i) => i % 2 === 0)
.style("background", "#eee");
Стили применяются только к элементам с чётным индексом.
this внутри .filter()Внутри обычной функции this указывает на текущий
DOM-элемент.
d3.selectAll("rect")
.filter(function() {
return this.getAttribute("width") > 100;
})
.attr("fill", "orange");
Здесь фильтрация выполняется по атрибуту DOM-элемента.
Стрелочные функции не имеют собственного this.
Неправильно:
.filter(() => {
return this.classList.contains("active");
})
Правильно:
.filter(function() {
return this.classList.contains("active");
})
.filter() может принимать строку-селектор.
d3.selectAll("div")
.filter(".active")
.style("color", "blue");
Будут выбраны только элементы с классом active.
| Подход | Возможности |
|---|---|
| CSS-селектор | Простая фильтрация по классам, тегам, атрибутам |
| Callback-функция | Полный контроль над логикой |
Метод особенно полезен при построении визуализаций.
const data = [15, 42, 8, 33, 27];
const svg = d3.select("body")
.append("svg")
.attr("width", 400)
.attr("height", 200);
svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", (d, i) => i * 60)
.attr("y", d => 200 - d * 4)
.attr("width", 50)
.attr("height", d => d * 4)
.attr("fill", "steelblue")
.filter(d => d > 30)
.attr("fill", "crimson");
Все прямоугольники создаются с синим цветом, затем фильтр выбирает
значения больше 30 и перекрашивает их в красный.
.filter() с другими методами.attr()d3.selectAll("circle")
.filter(d => d.active)
.attr("r", 10);
.style()d3.selectAll("text")
.filter((d, i) => i < 3)
.style("font-weight", "bold");
.remove()d3.selectAll("p")
.filter(function() {
return this.textContent === "";
})
.remove();
Удаляются пустые элементы.
.classed()d3.selectAll("path")
.filter(d => d.selected)
.classed("highlight", true);
.filter() от
.select().select()Выбирает один вложенный элемент.
selection.select("span")
.filter()Отбирает элементы из уже существующей выборки.
selection.filter(".active")
.filter() от
.selectAll().selectAll()Создаёт новую выборку по селектору.
d3.selectAll(".item")
.filter()Работает только с текущей выборкой.
selection.filter(".item")
d3.selectAll("circle")
.filter(function(d, i) {
return d.value > 50 && i < 5;
})
.attr("fill", "green");
Фильтрацию можно выполнять последовательно.
d3.selectAll("rect")
.filter(d => d.visible)
.filter(d => d.value > 100)
.attr("stroke", "black");
d3.selectAll("g")
.filter(function() {
return d3.select(this).selectAll("circle").size() > 3;
})
.attr("opacity", 0.5);
Метод часто применяется после связывания данных.
const items = svg.selectAll("circle")
.data(data)
.enter()
.append("circle");
items
.filter(d => d > 50)
.attr("fill", "red");
.filter() при анимацияхd3.selectAll("rect")
.filter(d => d.changed)
.transition()
.duration(1000)
.attr("height", d => d.value);
Анимация применяется только к изменённым элементам.
.filter() перебирает все элементы выборки. При работе с
большими объёмами данных важно учитывать стоимость вычислений.
Плохо:
.filter(d => complexCalculation(d))
Лучше заранее вычислить значения:
data.forEach(d => {
d.valid = complexCalculation(d);
});
selection.filter(d => d.valid);
Плохо:
.filter(function() {
return this.offsetWidth > 100;
})
DOM-операции относительно дорогие.
.filter() не изменяет порядок элементов в выборке.
d3.selectAll("div")
.filter((d, i) => i < 2);
Первые два элемента сохраняют исходный порядок.
Исходная выборка не изменяется.
const all = d3.selectAll("circle");
const large = all.filter(d => d > 100);
all содержит все элементы;large — только отфильтрованные.thisНеправильно:
.filter(() => this.checked)
Правильно:
.filter(function() {
return this.checked;
})
Неправильно:
.filter((d) => {
d > 10;
})
Правильно:
.filter((d) => {
return d > 10;
})
или
.filter(d => d > 10)
.filter() массива и D3D3-фильтрация работает с выборками DOM-элементов, а не с обычными массивами.
Массив:
array.filter(...)
D3:
selection.filter(...)
const data = [
{name: "A", value: 10},
{name: "B", value: 50},
{name: "C", value: 80},
{name: "D", value: 20}
];
const rows = d3.select("body")
.append("table")
.selectAll("tr")
.data(data)
.enter()
.append("tr");
rows.append("td")
.text(d => d.name);
rows.append("td")
.text(d => d.value);
rows
.filter(d => d.value > 40)
.style("background", "#ffdcdc");
simulationNodes
.filter(d => d.type === "server")
.attr("r", 12)
.attr("fill", "orange");
d3.selectAll(".item")
.filter(d => !d.visible)
.style("display", "none");
.filter() создаёт новую группу элементов, содержащую
ссылки только на подходящие DOM-узлы.
Концептуально работа похожа на:
const filtered = nodes.filter(condition);
Но D3 дополнительно сохраняет структуру групп выборки и контекст данных.
.filter()Метод особенно полезен в следующих ситуациях:
Если требуется только визуальное оформление по классам, предпочтительнее CSS.
Вместо:
selection.filter(".active")
.style("color", "red");
Иногда лучше:
.active {
color: red;
}
D3-фильтрация особенно ценна при динамических условиях, зависящих от данных.
.filter()
и событийd3.selectAll("circle")
.on("click", function(event, d) {
d3.selectAll("circle")
.filter(node => node.group === d.group)
.attr("fill", "red");
});
После клика выделяются элементы той же группы.
d3.selectAll("rect")
.filter(d => d.active)
.each(function(d) {
console.log(d);
});
.each() будет вызван только для отфильтрованных
элементов.
selection
.filter(условие)
.дальнейшие_операции()
Этапы: