В D3.js управление элементами DOM строится вокруг механизма выборок
(selection). После выбора элементов библиотека
предоставляет набор методов для изменения их атрибутов, CSS-стилей,
классов и свойств. Основные инструменты для этого:
.attr() — работа с HTML- и SVG-атрибутами;.style() — управление CSS-стилями;.classed() — добавление и удаление CSS-классов;.property() — работа со свойствами DOM-объектов.Эти методы поддерживают:
method chaining)..attr().attr()Метод .attr() используется для установки, чтения и
удаления HTML- или SVG-атрибутов.
Общий синтаксис:
selection.attr(name, value)
Где:
name — имя атрибута;value — значение атрибута.d3.select("div")
.attr("id", "container");
Результат:
<div id="container"></div>
D3.js активно использует цепочки методов:
d3.select("svg")
.attr("width", 600)
.attr("height", 400)
.attr("viewBox", "0 0 600 400");
.attr() и SVGМетод особенно важен при работе с SVG, поскольку SVG практически полностью управляется атрибутами.
d3.select("svg")
.append("circle")
.attr("cx", 100)
.attr("cy", 100)
.attr("r", 50);
d3.select("circle")
.attr("fill", "steelblue");
d3.select("rect")
.attr("x", 50)
.attr("y", 30)
.attr("width", 200)
.attr("height", 100);
Если второй аргумент отсутствует, метод возвращает значение атрибута.
const width = d3.select("svg").attr("width");
console.log(width);
Если передать null, атрибут удаляется.
d3.select("div")
.attr("id", null);
.attr()Одно из главных преимуществ D3 — возможность вычислять значения динамически.
.attr(name, function(d, i) {
return value;
})
Аргументы функции:
d — связанные данные;i — индекс элемента;nodes — массив элементов;this — текущий DOM-элемент.const data = [50, 120, 80];
d3.select("svg")
.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", (d, i) => i * 60)
.attr("y", d => 200 - d)
.attr("width", 40)
.attr("height", d => d);
Здесь:
.attr("data-index", (d, i) => i)
Результат:
<div data-index="0"></div>
<div data-index="1"></div>
<div data-index="2"></div>
data-*d3.selectAll("li")
.attr("data-active", "true");
.attr("stroke-width", 3)
.attr("stroke", "black")
.style().style()Метод .style() управляет встроенными CSS-стилями
элемента.
Синтаксис:
selection.style(name, value)
d3.select("div")
.style("color", "white")
.style("background", "black");
Результат:
<div style="color:white; background:black;"></div>
.attr()
и .style().attr().attr("fill", "red")
Это SVG-атрибут.
.style().style("fill", "red")
Это CSS-свойство.
CSS-стили часто имеют более высокий приоритет, чем атрибуты.
Например:
.attr("fill", "red")
.style("fill", "blue")
Итоговый цвет:
blue
const color = d3.select("div").style("color");
d3.select("div")
.style("color", null);
const data = [10, 50, 90];
d3.select("body")
.selectAll("div")
.data(data)
.enter()
.append("div")
.style("width", d => `${d}px`)
.style("background", d => d > 50 ? "red" : "green");
D3 не добавляет единицы автоматически.
Неверно:
.style("width", 100)
Верно:
.style("width", "100px")
d3.select(":root")
.style("--main-color", "orange");
Хотя .style() удобен, массовое оформление чаще выполняют
через классы.
Причины:
.classed().classed()Метод .classed() добавляет, удаляет и проверяет
CSS-классы.
Синтаксис:
selection.classed(name, value)
d3.select("div")
.classed("active", true);
Результат:
<div class="active"></div>
d3.select("div")
.classed("active", false);
Если второй аргумент отсутствует:
const hasClass = d3.select("div")
.classed("active");
d3.select("div")
.classed("visible selected highlighted", true);
const scores = [20, 70, 90];
d3.select("body")
.selectAll("p")
.data(scores)
.enter()
.append("p")
.text(d => d)
.classed("high-score", d => d > 50);
.high-score {
color: red;
font-weight: bold;
}
.classed("high-score", d => d > 50)
.classed()
от .attr("class").attr().attr("class", "box")
Полностью заменяет список классов.
.classed().classed("box", true)
Работает точечно и безопасно.
selection.classed("active", function() {
return !d3.select(this).classed("active");
});
.property().property().property() работает со свойствами DOM-объектов, а не с
HTML-атрибутами.
Синтаксис:
selection.property(name, value)
Это один из самых важных моментов при работе с DOM.
<input value="Hello">
HTML хранит исходное значение.
input.value
DOM хранит текущее состояние элемента.
const value = d3.select("input")
.property("value");
d3.select("input")
.property("value", "Новое значение");
d3.select("input[type='checkbox']")
.property("checked", true);
const checked = d3.select("input")
.property("checked");
d3.select("button")
.property("disabled", true);
d3.select("option")
.property("selected", true);
.property().property() предпочтителен для:
valuecheckedselecteddisabledselectedIndexfiles.attr().attr() подходит для:
id;data-*;href;src;viewBox;width;height.d3.select("svg")
.append("circle")
.attr("cx", 150)
.attr("cy", 100)
.attr("r", 40)
.style("fill", "orange")
.style("stroke", "black")
.style("stroke-width", "2px")
.classed("animated", true);
Все методы поддерживают вычисляемые значения.
const data = [30, 60, 90];
d3.select("svg")
.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", (d, i) => i * 100 + 50)
.attr("cy", 100)
.attr("r", d => d / 3)
.style("fill", d => d > 50 ? "tomato" : "steelblue")
.classed("large", d => d > 70);
thisВнутри callback-функций:
.attr("width", function() {
console.log(this);
})
this указывает на текущий DOM-элемент.
.style("opacity", function(d, i, nodes) {
console.log(nodes[i]);
return 1;
})
Изменения DOM являются дорогими операциями.
Эффективнее:
selection
.attr("x", 10)
.attr("y", 20)
.attr("width", 100);
чем многократные повторные выборки:
d3.select("rect").attr("x", 10);
d3.select("rect").attr("y", 20);
d3.select("rect").attr("width", 100);
Предпочтительно:
.classed("bar", true)
вместо:
.style("fill", "steelblue")
.style("stroke", "black")
.style("stroke-width", "1px")
.attr() и .property()Неверно:
.attr("checked", true)
Корректнее:
.property("checked", true)
Неверно:
.style("height", 200)
Верно:
.style("height", "200px")
Опасно:
.attr("class", "active")
Это удалит остальные классы.
Безопаснее:
.classed("active", true)
<svg width="500" height="300"></svg>
.bar {
fill: steelblue;
}
.bar:hover {
fill: orange;
}
.large {
stroke: black;
stroke-width: 2px;
}
const data = [40, 90, 130, 70, 160];
const svg = d3.select("svg");
svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", (d, i) => i * 90)
.attr("y", d => 300 - d)
.attr("width", 70)
.attr("height", d => d)
.classed("bar", true)
.classed("large", d => d > 100)
.style("cursor", "pointer");
| Метод | Назначение | Пример |
|---|---|---|
.attr() |
HTML/SVG-атрибуты | attr("width", 300) |
.style() |
CSS-стили | style("color", "red") |
.classed() |
CSS-классы | classed("active", true) |
.property() |
DOM-свойства | property("checked", true) |
Предпочтительно:
.attr()
Предпочтительно:
.classed()
и CSS.
Предпочтительно:
.property()
Подходит:
.style()
Типичный современный стиль работы с D3:
.attr()..classed()..style()..property().Такой подход обеспечивает: