Сигналы ширины и высоты

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

Каждый сигнал в Vega — это именованное значение, которое может изменяться во времени и автоматически триггерить перерасчёт зависимых выражений. Сигналы width и height занимают особое место: они определяют геометрию всего холста визуализации и одновременно могут быть переопределены через выражения.


Базовая модель width и height как сигналов

В Vega верхнеуровневые свойства width и height могут быть заданы как:

  • фиксированные числа
  • выражения сигналов
  • зависимости от внешнего контейнера
  • вычисляемые значения

Простейшая форма:

{
  "width": 400,
  "height": 300
}

Внутри системы это автоматически транслируется в сигналы:

{
  "signals": [
    { "name": "width", "value": 400 },
    { "name": "height", "value": 300 }
  ]
}

Однако ключевая особенность Vega заключается в том, что эти значения не статичны — они могут быть реактивно переопределены.


Сигнальная природа размеров

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

{
  "width": "containerSize()[0]",
  "height": "containerSize()[1]"
}

Здесь используется встроенный механизм сигналов:

  • containerSize() возвращает текущие размеры контейнера
  • индекс [0] — ширина
  • индекс [1] — высота

Таким образом, визуализация становится адаптивной без необходимости ручного пересчёта layout.


Взаимосвязь сигналов width и height с системой пересчёта

В Vega сигналы образуют направленный граф зависимостей. Если width зависит от другого сигнала, например:

{
  "signals": [
    {
      "name": "padding",
      "value": 20
    },
    {
      "name": "width",
      "update": "containerSize()[0] - padding * 2"
    }
  ]
}

то любое изменение padding автоматически приводит к пересчёту width.

Важно:

  • width и height участвуют в layout-движке
  • они влияют на шкалы (scale.range)
  • они влияют на оси (axis)
  • они влияют на геометрию mark-ов

Использование width и height в вычислении шкал

Ширина и высота напрямую участвуют в формировании диапазонов шкал.

Пример:

{
  "scales": [
    {
      "name": "xscale",
      "range": [0, { "signal": "width" }]
    }
  ]
}

И аналогично:

{
  "scales": [
    {
      "name": "yscale",
      "range": [{ "signal": "height" }, 0]
    }
  ]
}

Здесь важно, что height часто инвертируется (0 вверху), что типично для SVG-координатной системы.


Динамическое изменение размеров

Сигналы позволяют изменять размеры визуализации в рантайме:

{
  "signals": [
    {
      "name": "chartWidth",
      "value": 400
    },
    {
      "name": "width",
      "update": "chartWidth"
    }
  ]
}

Изменение chartWidth автоматически перестраивает:

  • оси
  • сетку
  • положение маркеров
  • диапазоны шкал

Связь с контейнером и autosize

Механизм autosize управляет тем, как Vega интерпретирует width и height.

Основные режимы:

{
  "autosize": "pad"
}
{
  "autosize": "fit"
}
{
  "autosize": "none"
}

Поведение:

  • pad — добавляет отступы к заданным width/height
  • fit — подгоняет визуализацию под контейнер
  • none — фиксирует размеры без адаптации

При fit сигналы width и height фактически становятся производными от контейнера.


Сигналы width и height в событиях окна

Vega поддерживает привязку к событиям изменения окна:

{
  "signals": [
    {
      "name": "width",
      "on": [
        {
          "events": "window:resize",
          "update": "containerSize()[0]"
        }
      ]
    }
  ]
}

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

  • изменение размера окна → событие window:resize
  • пересчёт контейнера
  • обновление сигнала width
  • перерасчёт всех зависимостей

Различие поведения в Vega-Lite

В Vega-Lite width и height задаются на более высоком уровне абстракции и не описываются напрямую как сигналы в пользовательской спецификации.

Пример Vega-Lite:

{
  "width": "container",
  "height": 300
}

или:

{
  "width": 400,
  "height": 300
}

При компиляции:

  • Vega-Lite преобразует width и height в сигналы Vega
  • добавляет autosize поведение
  • формирует внутренние зависимости layout

Контейнерный режим Vega-Lite

{
  "width": "container",
  "height": "container"
}

Это эквивалентно:

  • привязке к DOM-элементу
  • динамическому пересчёту при resize
  • генерации сигналов width и height в Vega runtime

Влияние width и height на layout маркировки

Размеры холста влияют на:

1. Позиционирование mark-ов

{
  "mark": "bar",
  "encoding": {
    "x": { "field": "category" },
    "y": { "field": "value" }
  }
}

Если width увеличивается:

  • бары перераспределяются по оси X
  • увеличивается доступное пространство между категориями

2. Шаговые шкалы (step-based layout)

При дискретных шкалах:

{
  "width": { "step": 20 }
}

Общая ширина вычисляется как:

  • число категорий × step
  • плюс padding

Это создаёт обратную зависимость: не только width влияет на данные, но и данные влияют на width.


Выражения с зависимостью от width и height

Сигналы можно использовать в выражениях:

{
  "signals": [
    {
      "name": "radius",
      "update": "min(width, height) / 2"
    }
  ]
}

Это особенно важно для:

  • круговых диаграмм
  • радиальных layout-ов
  • диаграмм с центрированием

Иерархия сигналов размеров

Система вычислений обычно выглядит так:

  1. внешний контейнер (DOM)
  2. autosize
  3. width/height сигналы
  4. пользовательские производные сигналы
  5. scales
  6. marks

Любое изменение на верхнем уровне распространяется вниз по графу зависимостей.


Типичные ошибки при работе с width и height

1. Циклические зависимости

{
  "signals": [
    {
      "name": "width",
      "update": "height + 10"
    },
    {
      "name": "height",
      "update": "width - 10"
    }
  ]
}

Такая конструкция создаёт замкнутый цикл и приводит к некорректному пересчёту.


2. Потеря адаптивности

{
  "autosize": "none",
  "width": 800
}

В этом случае визуализация перестаёт реагировать на контейнер, что часто ломает responsive layout.


3. Несогласованность шкал

Если width меняется, но шкалы фиксированы, возможны:

  • обрезание данных
  • наложение элементов
  • некорректная плотность отображения

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

При проектировании визуализации важно учитывать, что width и height — это не просто параметры, а входные переменные всей системы визуального вычисления.

Они:

  • управляют геометрией
  • участвуют в вычислениях шкал
  • реагируют на события DOM
  • могут быть производными от других сигналов
  • определяют масштаб визуального восприятия данных

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