В визуализации на основе декларативной модели порядок отображения объектов определяется не только их координатами, но и системой слоёв. При совпадении или пересечении геометрий решающим становится правило painter’s algorithm: элементы, отрисованные позже, перекрывают предыдущие.
В Vega и Vega-Lite управление этим поведением осуществляется через параметр zindex, который задаёт приоритет слоя среди других графических примитивов внутри одного визуального представления.
Ключевая особенность механизма заключается в том, что zindex не влияет на данные и не изменяет геометрию. Он воздействует исключительно на порядок компоновки графических объектов перед финальной отрисовкой.
В Vega каждая графическая сущность (mark) может иметь свойство
zindex, определяющее порядок её отрисовки относительно
других marks в одном и том же наборе.
{
"marks": [
{
"type": "rect",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "x"},
"x2": {"scale": "x", "field": "x2"},
"y": {"scale": "y", "field": "y"},
"y2": {"scale": "y", "field": "y2"},
"fill": {"value": "steelblue"},
"zindex": {"value": 0}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "x"},
"y": {"scale": "y", "field": "y"},
"text": {"field": "label"},
"fill": {"value": "black"},
"zindex": {"value": 1}
}
}
}
]
}
В этом примере текст всегда оказывается поверх прямоугольников,
поскольку имеет более высокий zindex.
В Vega порядок отрисовки определяется не только значением zindex, но и структурой данных:
Это означает, что стабильность результата зависит от комбинации двух факторов:
Vega-Lite предоставляет более высокий уровень абстракции и чаще скрывает детали рендеринга. Однако zindex остаётся доступным через encoding и используется для управления перекрытием визуальных элементов внутри одного слоя.
В Vega-Lite zindex задаётся как канал encoding:
{
"data": {"values": [
{"x": 1, "y": 3, "type": "A"},
{"x": 2, "y": 5, "type": "B"}
]},
"mark": "point",
"encoding": {
"x": {"field": "x", "type": "quantitative"},
"y": {"field": "y", "type": "quantitative"},
"color": {"field": "type", "type": "nominal"},
"zindex": {"field": "type", "type": "ordinal"}
}
}
Здесь порядок определяется значением категории type,
преобразованной в порядок отрисовки.
Используется для статического управления слоями:
"zindex": {"value": 1}
Применение:
Значение может зависеть от данных:
"zindex": {"field": "importance"}
или через трансформацию:
"zindex": {"expr": "datum.value > 10 ? 2 : 0"}
Такой подход позволяет динамически изменять порядок визуальных элементов в зависимости от состояния данных.
Vega-Lite активно использует layered marks:
При использовании составных графиков порядок слоёв часто определяется структурой specification, но zindex позволяет переопределить этот порядок внутри слоя.
Пример конфликтного наложения:
{
"layer": [
{
"mark": {"type": "area", "opacity": 0.3},
"encoding": {
"x": {"field": "x", "type": "quantitative"},
"y": {"field": "y", "type": "quantitative"}
}
},
{
"mark": "line",
"encoding": {
"x": {"field": "x"},
"y": {"field": "y"},
"zindex": {"value": 1}
}
},
{
"mark": "point",
"encoding": {
"x": {"field": "x"},
"y": {"field": "y"},
"size": {"value": 80},
"zindex": {"value": 2}
}
}
]
}
Здесь zindex используется для тонкой настройки поверхностного порядка внутри одного слоя, несмотря на наличие layer-конструкции.
При использовании событий (hover, click, selection) zindex становится инструментом визуальной приоритизации активных элементов.
Типичный сценарий:
"zindex": {
"condition": {
"selection": "hover",
"value": 10
},
"value": 0
}
Это обеспечивает мгновенное визуальное выделение без изменения геометрии или данных.
Несмотря на гибкость, zindex имеет ряд ограничений:
zindex работает внутри одного визуального контекста (mark group). Он не гарантирует порядок между независимыми view.
Layer задаёт архитектурный порядок, zindex — локальную корректировку.
Элементы декора (grid, axis) управляются системой компоновки Vega-Lite и не всегда подчиняются zindex.
Когда слой уже определяет порядок, попытка управлять им через zindex может давать неожиданный результат.
Использование числового поля как ordinal без явной шкалы приводит к нестабильной сортировке.
zindex не решает проблемы визуальной композиции, связанные с масштабом или прозрачностью.
Если несколько элементов имеют одинаковый zindex:
Это делает результат потенциально недетерминированным при сложных преобразованиях данных.
zindex не оказывает значительного влияния на вычислительную сложность, поскольку сортировка выполняется на этапе подготовки сцены. Однако при больших наборах данных с вычисляемым zindex:
Особенно это заметно при использовании выражений expr,
зависящих от вычисляемых полей.
При использовании opacity и blend режимов zindex остаётся верхнеуровневым механизмом порядка, но визуальное восприятие может изменяться:
Это часто используется в плотных scatterplot визуализациях для уменьшения визуального шума.
В многослойных дашбордах Vega-Lite zindex становится инструментом локального контроля:
При этом архитектурный порядок остаётся за layer и resolve-логикой, а zindex выполняет роль тонкой корректировки визуальной иерархии.