Текстовые представления данных в D3.js опираются на базовый принцип связывания данных с DOM-элементами, где визуализация может быть выражена не только графически (SVG, Canvas), но и через структурированный текст. Такой подход используется в таблицах, подписях, аннотациях, динамических отчетах и интерфейсах, где информация должна оставаться читаемой без графической интерпретации.
Основой служит механизм data join, позволяющий сопоставлять массив
данных с набором DOM-узлов и управлять их текстовым содержимым через
.text().
d3.select("body")
.selectAll("p")
.data([10, 20, 30])
.join("p")
.text(d => `Значение: ${d}`);
Каждый элемент массива превращается в текстовый узел, где функция доступа определяет формат вывода.
Текстовые представления в D3.js чаще всего реализуются через HTML-элементы. В отличие от SVG-графики, текстовые узлы не требуют координатной системы и напрямую отражают структуру данных.
const dataset = [
{ name: "A", value: 12 },
{ name: "B", value: 45 },
{ name: "C", value: 7 }
];
d3.select("body")
.selectAll("div")
.data(dataset)
.join("div")
.text(d => `${d.name}: ${d.value}`);
При изменении данных обновление текста происходит через повторное связывание и обновление selection.
D3 предоставляет модуль форматирования чисел d3-format,
позволяющий приводить данные к человекочитаемому виду. Это критично для
текстовых представлений, где точность и компактность важнее визуальной
выразительности.
const f = d3.format(".2f");
d3.selectAll("div")
.text(d => `Значение: ${f(d.value)}`);
Поддерживаются форматы:
d3.format(",.0f")(1234567); // "1,234,567"
В некоторых случаях текст заменяет графическую интерпретацию данных. Это особенно характерно для компактных информационных панелей и таблиц.
const stats = d3.select("body")
.append("pre")
.text(() => {
const data = [5, 10, 15, 20];
return `
Среднее: ${d3.mean(data)}
Минимум: ${d3.min(data)}
Максимум: ${d3.max(data)}
`;
});
Функции d3.mean, d3.median,
d3.min, d3.max позволяют формировать текстовые
сводки без визуальных элементов.
Модуль d3-array предоставляет инструменты группировки,
позволяющие формировать структурированные текстовые отчеты.
const data = [
{ group: "X", value: 10 },
{ group: "X", value: 20 },
{ group: "Y", value: 5 }
];
const grouped = d3.group(data, d => d.group);
grouped.forEach((values, key) => {
console.log(key, d3.sum(values, d => d.value));
});
Для текстового представления DOM:
d3.select("body")
.selectAll("div")
.data(Array.from(grouped))
.join("div")
.text(([key, values]) =>
`${key}: ${d3.sum(values, d => d.value)}`
);
HTML-таблицы часто выступают альтернативой графическим представлениям.
const table = d3.select("body")
.append("table");
const rows = table.selectAll("tr")
.data(dataset)
.join("tr");
rows.selectAll("td")
.data(d => [d.name, d.value])
.join("td")
.text(d => d);
Такой подход сохраняет связь данных с DOM и позволяет обновлять таблицу через повторное связывание.
D3 управляет жизненным циклом элементов через enter, update и exit, что одинаково применимо к текстовым представлениям.
const update = d3.select("body")
.selectAll("div")
.data([1, 2, 3, 4]);
update.join(
enter => enter.append("div").text(d => `Новый: ${d}`),
update => update.text(d => `Обновлён: ${d}`),
exit => exit.remove()
);
Изменение текста происходит без пересоздания узлов, что снижает нагрузку на DOM.
Модуль d3-time-format используется для текстового
отображения временных данных.
const format = d3.timeFormat("%Y-%m-%d");
d3.selectAll("div")
.text(d => format(new Date(d.date)));
Возможны локализованные форматы:
const locale = d3.timeFormatLocale({
dateTime: "%A, %e %B %Y г., %X",
date: "%d.%m.%Y",
time: "%H:%M:%S",
periods: ["AM", "PM"],
days: [],
shortDays: [],
months: [],
shortMonths: []
});
SVG-элементы text используются для аннотаций, подписей и
пояснений внутри графиков.
d3.select("svg")
.append("text")
.attr("x", 50)
.attr("y", 50)
.text("Подпись данных");
Связывание данных с SVG-текстом аналогично HTML-подходу:
d3.select("svg")
.selectAll("text")
.data(dataset)
.join("text")
.attr("x", (d, i) => i * 30)
.attr("y", 20)
.text(d => d.value);
Текстовые панели могут обновляться в реальном времени на основе входящих данных.
function render(data) {
const panel = d3.select("#panel");
panel.selectAll("p")
.data(data)
.join("p")
.text(d => `${d.metric}: ${d.value}`);
}
Такой подход используется в мониторинге метрик, логировании и аналитических интерфейсах.
Текст может формироваться не напрямую из данных, а через вычисления на лету.
d3.selectAll("div")
.text(d => `Отклонение: ${(d - d3.mean(dataset)).toFixed(2)}`);
Для более сложных случаев применяются композиции функций:
const normalize = (x, min, max) => (x - min) / (max - min);
d3.selectAll("div")
.text(d => normalize(d, d3.min(dataset), d3.max(dataset)));
Текстовая форма часто служит основой доступных интерфейсов. Атрибуты ARIA позволяют связывать визуальные элементы с текстовыми описаниями.
d3.selectAll("rect")
.attr("aria-label", d => `Значение ${d.value}`)
.attr("role", "img");
Дополнительные текстовые описания могут дублировать графику для экранных читалок.
При работе с динамическими данными важно учитывать экранирование специальных символов HTML.
function escapeHTML(str) {
return str
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">");
}
d3.selectAll("div")
.html(d => escapeHTML(d.text));
Использование .text() предпочтительнее
.html() при текстовых представлениях.
D3 поддерживает локализацию через форматирование чисел и дат, что критично для международных интерфейсов.
const locale = d3.formatLocale({
decimal: ",",
thousands: " ",
grouping: [3],
currency: ["₸", ""]
});
const f = locale.format("$.2f");
Текстовые узлы дешевле графических, но при массовых обновлениях требуют оптимизации:
d3.selectAll("div")
.data(dataset, d => d.id)
.join("div")
.text(d => d.value);
Текстовые элементы часто комбинируются с графическими слоями, образуя гибридные представления, где числа, подписи и описания дополняют визуальные сигналы, сохраняя структуру данных в явной форме через DOM-связку и функции доступа.