Поле labelOverlap в Vega и Vega-Lite отвечает за
автоматическое устранение наложения текстовых подписей на осях. При
высокой плотности данных подписи осей начинают пересекаться, становясь
нечитаемыми. Механизм labelOverlap управляет стратегией
отбора или скрытия части меток так, чтобы сохранить визуальную ясность
без ручной настройки каждого тика.
При построении графиков ось формирует набор подписей (tick labels), которые отображают значения шкалы. В ситуациях, когда:
подписи начинают накладываться друг на друга. Это приводит к потере читаемости и визуальному шуму.
Механизм labelOverlap вмешивается на этапе рендеринга и
применяет алгоритм фильтрации меток.
В Vega-Lite свойство задаётся внутри описания оси:
{
"mark": "line",
"encoding": {
"x": {
"field": "date",
"type": "temporal",
"axis": {
"labelOverlap": "greedy"
}
},
"y": {
"field": "value",
"type": "quantitative"
}
}
}
В Vega (низкоуровневой спецификации) аналогичная логика применяется через настройки axis:
{
"axes": [
{
"scale": "xscale",
"orient": "bottom",
"labelOverlap": true
}
]
}
Исторически использовалось логическое значение:
true — включение стандартного алгоритма устранения
перекрытийfalse — отключение обработки, все метки
отображаютсяВ современных версиях Vega-Lite boolean-режим считается упрощённым интерфейсом.
Режим "greedy" реализует жадный алгоритм отбора:
Особенности:
Применение:
{
"axis": {
"labelOverlap": "greedy"
}
}
Режим "parity" использует более сбалансированный
подход:
Применение:
{
"axis": {
"labelOverlap": "parity"
}
}
Особенности:
Оба алгоритма работают на уровне пост-обработки шкалы после вычисления tick values. Порядок обработки:
Ключевым ограничением является то, что labelOverlap не
изменяет шкалу — он лишь скрывает часть визуальных элементов.
Поведение labelOverlap напрямую зависит от типа
шкалы:
Для числовых и временных осей:
labelOverlap активно уменьшает плотностьДля категориальных осей:
Поворот подписей влияет на частоту срабатывания
labelOverlap:
{
"axis": {
"labelAngle": -45,
"labelOverlap": "greedy"
}
}
При наклоне текста количество пересечений уменьшается, и алгоритм может сохранять больше меток.
Сокращение текста уменьшает bounding box:
Параметр tickCount задаёт желаемое количество
делений:
{
"mark": "line",
"encoding": {
"x": {
"field": "timestamp",
"type": "temporal",
"axis": {
"labelOverlap": "parity",
"labelAngle": 0
}
},
"y": {
"field": "temperature",
"type": "quantitative"
}
}
}
Временные оси часто содержат плотные значения, поэтому
parity обеспечивает равномерное прореживание.
{
"mark": "bar",
"encoding": {
"x": {
"field": "category",
"type": "nominal",
"axis": {
"labelAngle": -40,
"labelOverlap": "greedy"
}
},
"y": {
"field": "count",
"type": "quantitative"
}
}
}
Здесь жадный алгоритм сохраняет максимальное количество категорий, скрывая только конфликтующие.
labelOverlap не решает фундаментальные проблемы
перегруженных осей:
При критической плотности данных возможна ситуация, когда остаётся слишком мало видимых подписей, что снижает информативность графика.
Внутренне Vega вычисляет bounding boxes меток уже после применения форматирования текста. Это означает:
timeFormat или format может
изменить результат работы алгоритмаМногострочные подписи увеличивают вертикальный размер bounding box, что усиливает вероятность перекрытий:
{
"axis": {
"labelExpr": "datum.label + '\\n' + datum.value",
"labelOverlap": "greedy"
}
}
В таких случаях parity часто даёт более стабильный
результат, чем greedy.
Алгоритмы labelOverlap оптимизированы под линейную
сложность относительно количества меток:
При больших наборах данных разница становится заметной, особенно в интерактивных визуализациях.
При изменении размеров контейнера:
Это приводит к “плавающему” количеству подписей при responsive-визуализациях.