Иерархическая визуализация данных через treemap строится на принципе рекурсивного деления прямоугольной области на вложенные прямоугольники, пропорциональные значениям узлов. Ключевую роль в этом процессе играет функция распределения пространства — стратегия тайлинга (tiling strategy), определяющая геометрию разбиения на каждом уровне иерархии.
В D3.js стратегии тайлинга передаются в метод .tile()
объекта d3.treemap() и влияют на внешний вид карты,
читаемость структуры и восприятие относительных величин.
Перед рассмотрением конкретных стратегий важно понимать базовый конвейер:
d3.hierarchy..sum() или
.count()).d3.treemap().Базовый пример:
const root = d3.hierarchy(data)
.sum(d => d.value)
.sort((a, b) => b.value - a.value);
d3.treemap()
.size([width, height])
.padding(1)
.tile(d3.treemapSquarify)(root);
treemapSquarify минимизирует отклонение прямоугольников
от квадрата. Алгоритм стремится к тому, чтобы соотношение сторон каждого
блока было максимально близким к 1:1.
Основная идея заключается в последовательном размещении элементов в строки (или столбцы) с проверкой «плохой» метрики — worst aspect ratio.
Алгоритм минимизирует:
[ ( )]
где ( w ) и ( h ) — ширина и высота прямоугольника.
d3.treemap()
.tile(d3.treemapSquarify)
.size([800, 600])
(root);
treemapSlice выполняет последовательное разбиение
пространства только по горизонтальной оси. Каждый уровень иерархии делит
доступную область на вертикальные полосы (slices).
Каждый набор элементов получает одинаковую высоту, но различную ширину:
d3.treemap()
.tile(d3.treemapSlice)
.size([800, 600])
(root);
treemapDice является зеркальным аналогом
treemapSlice. Разбиение происходит по вертикальной оси,
создавая горизонтальные полосы (dice-подобные сегменты).
d3.treemap()
.tile(d3.treemapDice)
.size([800, 600])
(root);
| Стратегия | Ось разбиения | Форма блоков |
|---|---|---|
| treemapSquarify | адаптивная | близкие к квадратам |
| treemapSlice | горизонтальная | вертикальные полосы |
| treemapDice | вертикальная | горизонтальные полосы |
При одинаковых входных данных результат визуализации может существенно различаться:
D3.js позволяет переключать стратегию динамически, что используется при интерактивных интерфейсах:
const treemap = d3.treemap()
.size([width, height])
.padding(2);
function update(mode) {
if (mode === "squarify") {
treemap.tile(d3.treemapSquarify);
} else if (mode === "slice") {
treemap.tile(d3.treemapSlice);
} else if (mode === "dice") {
treemap.tile(d3.treemapDice);
}
treemap(root);
}
Хотя стратегия тайлинга определяет базовую геометрию, дополнительные параметры изменяют визуальный результат:
paddingInner — расстояния между соседними узламиpaddingOuter — отступы от границ контейнераpaddingTop — отступ для заголовков группКомбинация с treemapSquarify обычно даёт наиболее
стабильный визуальный результат, тогда как slice/dice усиливают
структурные разрывы.
Использование treemapSquarify обеспечивает равномерное
распределение блоков и упрощает сравнение метрик.
treemapSlice применяется для визуализации
последовательных процессов, где важна линейность.
treemapDice помогает выделять крупные категории и их
внутреннюю структуру.
Различия между стратегиями не влияют существенно на вычислительную сложность алгоритма treemap в D3.js, так как все три метода работают в рамках одного рекурсивного процесса:
При сильно неравномерных данных:
Порядок сортировки (.sort()) напрямую влияет на
результат тайлинга:
root.sort((a, b) => b.value - a.value);