Именованные шкалы в Vega

В Vega шкала (scale) представляет собой функцию отображения, преобразующую значения из доменного пространства данных (domain) в пространство визуализации (range). Ключевая особенность архитектуры Vega заключается в том, что шкалы являются именованными объектами, которые существуют независимо от визуальных элементов (marks) и могут переиспользоваться.

Именованная шкала — это шкала, которой явно присвоено уникальное имя, используемое для связи с маркерами, осями и легендами.

Основные свойства такого подхода:

  • отделение логики масштабирования от графических примитивов;
  • возможность повторного использования одной шкалы в разных mark-элементах;
  • централизованное управление визуальным преобразованием данных;
  • явная декларативность связей между данными и визуализацией.

Объявление шкал в Vega

В спецификации Vega шкалы определяются в разделе scales на верхнем уровне JSON-спеки. Каждая шкала представляет собой объект с обязательным полем name.

Пример базового объявления:

{
  "scales": [
    {
      "name": "xScale",
      "type": "linear",
      "domain": { "data": "table", "field": "value" },
      "range": "width"
    }
  ]
}

Ключевые поля именованной шкалы

  • name — уникальный идентификатор шкалы;
  • type — тип преобразования (linear, band, ordinal, time и др.);
  • domain — входной диапазон значений;
  • range — выходной диапазон (пиксели, цвета, углы);
  • clamp — ограничение значений внутри диапазона;
  • nice — округление границ домена;
  • padding / paddingInner / paddingOuter — управление отступами (для band/point шкал).

Связь шкалы с данными через domain

domain определяет, какие данные попадают в шкалу. В Vega возможны три основных способа задания:

1. Через данные

"domain": { "data": "table", "field": "value" }

Шкала автоматически вычисляет минимальное и максимальное значение поля.

2. Явный диапазон

"domain": [0, 100]

Используется фиксированный числовой диапазон.

3. Через выражения

"domain": { "signal": "domainValues" }

Позволяет динамически изменять диапазон через сигналы.


Использование именованных шкал в mark-элементах

Связь между данными и визуальными примитивами осуществляется через указание имени шкалы в encoding каналах.

Пример использования в прямоугольниках:

{
  "marks": [
    {
      "type": "rect",
      "from": { "data": "table" },
      "encode": {
        "enter": {
          "x": { "scale": "xScale", "field": "value" },
          "width": { "scale": "xScale", "value": 10 }
        }
      }
    }
  ]
}

Здесь ключевым моментом является:

“scale”: “xScale” — явная ссылка на именованную шкалу.

Это означает, что Vega не создаёт новую шкалу автоматически, а использует уже определённую.


Именованные шкалы и координатные системы

В Vega шкалы часто используются для построения координатных систем:

  • xScale — горизонтальная ось;
  • yScale — вертикальная ось;
  • colorScale — цветовое отображение;
  • sizeScale — масштабирование размеров;
  • opacityScale — управление прозрачностью.

Пример двухосевой системы:

"scales": [
  {
    "name": "xScale",
    "type": "band",
    "domain": { "data": "table", "field": "category" },
    "range": "width"
  },
  {
    "name": "yScale",
    "type": "linear",
    "domain": { "data": "table", "field": "value" },
    "range": "height"
  }
]

Повторное использование шкал

Одним из ключевых преимуществ именованных шкал является их переиспользование в нескольких mark-слоях.

Пример:

{
  "marks": [
    {
      "type": "rect",
      "from": { "data": "bars" },
      "encode": {
        "enter": {
          "x": { "scale": "xScale", "field": "category" },
          "y": { "scale": "yScale", "field": "value" }
        }
      }
    },
    {
      "type": "text",
      "from": { "data": "bars" },
      "encode": {
        "enter": {
          "x": { "scale": "xScale", "field": "category" },
          "y": { "scale": "yScale", "field": "value" },
          "text": { "field": "value" }
        }
      }
    }
  ]
}

В этом случае:

  • шкала xScale используется и для геометрии, и для текста;
  • обеспечивается полное совпадение позиционирования элементов;
  • исключается дублирование логики вычислений.

Шкалы и оси

В Vega оси (axes) напрямую связаны со шкалами. Каждая ось ссылается на именованную шкалу через поле scale.

{
  "axes": [
    {
      "scale": "xScale",
      "orient": "bottom"
    },
    {
      "scale": "yScale",
      "orient": "left"
    }
  ]
}

Особенность архитектуры:

  • шкала не зависит от оси;
  • ось является лишь визуализацией шкалы;
  • одна шкала может иметь несколько осей (например, зеркальные оси).

Шкалы и легенды

Для категориальных или цветовых шкал используется связь с легендами:

{
  "legends": [
    {
      "fill": "colorScale"
    }
  ]
}

Шкала colorScale может быть определена как:

{
  "name": "colorScale",
  "type": "ordinal",
  "domain": { "data": "table", "field": "category" },
  "range": ["red", "blue", "green"]
}

Таким образом:

  • шкала определяет соответствие категорий и цветов;
  • легенда отображает это соответствие пользователю;
  • связь остаётся декларативной и именованной.

Динамические именованные шкалы через сигналы

Vega позволяет управлять шкалами через сигналы (signals), что делает именованные шкалы реактивными.

Пример:

{
  "signals": [
    {
      "name": "maxValue",
      "value": 100
    }
  ],
  "scales": [
    {
      "name": "yScale",
      "type": "linear",
      "domain": [0, { "signal": "maxValue" }],
      "range": "height"
    }
  ]
}

Изменение maxValue приводит к автоматическому пересчёту шкалы.


Композиция шкал и многослойные визуализации

В сложных визуализациях шкалы часто разделяются по слоям, но при этом остаются именованными и совместимыми.

Типичный сценарий:

  • одна шкала используется для основного слоя;
  • другая — для вспомогательного (например, линия тренда);
  • третья — для аннотаций.

Важно, что именование позволяет явно контролировать:

  • какие слои используют общую систему координат;
  • какие используют независимую шкалу.

Типичные ошибки при работе с именованными шкалами

1. Конфликт имён

Если несколько шкал используют одно имя, поведение становится неопределённым:

  • одна шкала перезапишет другую;
  • ссылки в mark могут указывать на неожиданный объект.

2. Несоответствие domain

Если шкала используется повторно, но домены рассчитаны по разным данным, возникает визуальная несогласованность.

3. Смешивание типов шкал

Использование, например, band шкалы как числовой в линейных вычислениях приводит к искажению визуализации.

4. Отсутствие явной привязки

Если mark не указывает scale, Vega может создать неявную шкалу, что ломает архитектурную предсказуемость.


Продвинутые сценарии использования именованных шкал

Общая шкала для нескольких графиков

Одна шкала может использоваться в нескольких независимых визуальных блоках, обеспечивая единый масштаб восприятия.

Инверсия шкал

Vega поддерживает обратное отображение через invert:

{
  "name": "yScale",
  "type": "linear",
  "domain": [0, 100],
  "range": "height"
}

И затем:

"yScale": { "invert": 50 }

Позволяет получать исходное значение из координаты.

Композиция шкал через производные значения

Шкалы могут использовать результаты других шкал или сигналов:

  • масштабирование одного графика относительно другого;
  • синхронизация осей;
  • построение связанных визуализаций.

Именованные шкалы формируют основу архитектуры Vega, обеспечивая строгую декомпозицию между данными, преобразованиями и визуальными слоями, где каждая шкала становится независимым, переиспользуемым и явно адресуемым компонентом визуальной системы.