Концепция selection (выделение)

В экосистеме Vega и Vega-Lite selection представляет собой декларативный способ описания пользовательского выбора данных внутри визуализации. Это не просто обработка событий мыши или клавиатуры, а абстракция уровня модели данных, где взаимодействие рассматривается как трансформация состояния, влияющая на фильтрацию, стилизацию и вычисление производных значений.

Selection выступает связующим слоем между событиями интерфейса и декларативной спецификацией графика. Вместо императивного кода «при клике выделить точку» описывается правило: какое состояние считается выбранным, как оно обновляется и каким образом влияет на данные и визуальные каналы.

Базовая модель selection

В основе лежит идея параметра состояния. Selection — это именованное состояние, которое может:

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

В Vega-Lite selection описывается в секции selection, а затем применяется через:

  • transform (фильтрация данных),
  • encoding (условное отображение),
  • scale (динамическое масштабирование),
  • condition (ветвление визуальных свойств).

Типы selection

Point selection

Point selection фиксирует отдельные значения данных.

"selection": {
  "highlight": {
    "type": "point",
    "encodings": ["x", "y"],
    "on": "click",
    "toggle": true
  }
}

Point selection используется для:

  • выбора отдельных точек,
  • построения tooltip-подобных взаимодействий,
  • выделения категорий.

Ключевой механизм — сопоставление событий с точными значениями полей данных.

Interval selection

Interval selection формирует диапазон значений, чаще всего через прямоугольное выделение мышью.

"selection": {
  "brush": {
    "type": "interval",
    "encodings": ["x", "y"]
  }
}

Interval selection применяется для:

  • зумирования,
  • фильтрации диапазонов,
  • анализа плотности распределений.

Внутренне это представляется как набор границ по шкалам.

Multi selection

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

"selection": {
  "cats": {
    "type": "multi",
    "fields": ["category"],
    "toggle": "event.shiftKey"
  }
}

Multi selection формирует множество активных значений, где каждое новое событие добавляет или удаляет элемент.

Связь selection и данных

Selection напрямую интегрируется в поток данных через трансформации.

Фильтрация через selection

"transform": [
  {
    "filter": {
      "selection": "brush"
    }
  }
]

Фильтрация работает как предикат: каждая строка данных проверяется на принадлежность выбранному диапазону или множеству.

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

  • принадлежит ли значение диапазону interval selection,
  • совпадает ли поле с выбранным значением point selection.

Conditional encoding

Одно из ключевых применений selection — условное оформление элементов.

"mark": "circle",
"encoding": {
  "color": {
    "condition": {
      "selection": "highlight",
      "value": "red"
    },
    "value": "lightgray"
  }
}

Здесь selection становится переключателем визуального состояния.

Модель поведения:

  • если элемент входит в selection → один стиль,
  • если нет → альтернативный стиль.

Это превращает selection в декларативный state machine для визуальных свойств.

Scale binding

Selection может управлять масштабами осей.

"selection": {
  "zoom": {
    "type": "interval",
    "bind": "scales"
  }
}

При таком связывании:

  • выделенный диапазон изменяет domain шкалы,
  • визуализация становится интерактивным навигируемым пространством.

Это один из наиболее мощных механизмов, так как selection перестаёт быть только фильтром и становится инструментом управления системой координат.

Events и trigger-модель

Selection описывает не только состояние, но и триггеры его обновления:

  • on: событие (click, drag, mouseover),
  • clear: событие сброса,
  • toggle: логика переключения,
  • resolve: поведение при конфликте нескольких selection.

Пример:

"selection": {
  "sel": {
    "type": "point",
    "on": "mouseover",
    "clear": "mouseout"
  }
}

Модель событий абстрагируется от DOM и описывается как декларативный поток.

Resolve: поведение нескольких selection

Когда в визуализации существует несколько selection, возникает необходимость определения их взаимодействия:

  • union — объединение условий,
  • intersect — пересечение,
  • global — глобальное состояние,
  • independent — независимые области.
"selection": {
  "a": {"type": "point"},
  "b": {"type": "interval"},
  "resolve": "intersect"
}

Это определяет, как комбинируются предикаты выборки.

Selection в Vega (низкоуровневая модель)

В Vega selection реализуется через signals и event streams. Вместо декларативного блока используется комбинация:

  • signals,
  • event listeners,
  • expressions,
  • predicates.

Пример сигнальной модели:

"signals": [
  {
    "name": "brush",
    "on": [
      {
        "events": "@canvas:mousedown",
        "update": "[eventX(), eventY()]"
      }
    ]
  }
]

Здесь selection фактически становится производной сигналов, а логика выделения описывается через поток событий.

Predicates и логика принадлежности

Selection в Vega часто превращается в предикаты:

  • in — принадлежность значению,
  • range — попадание в интервал,
  • and/or/not — логические операции.

Эти предикаты используются в фильтрах и выражениях:

"transform": [
  {
    "filter": "datum.value > brush[0] && datum.value < brush[1]"
  }
]

Toggle и накопительные состояния

Toggle-механизм определяет, как selection изменяется при повторных взаимодействиях:

  • включение элемента при первом выборе,
  • исключение при повторном,
  • или полная замена состояния.
"selection": {
  "sel": {
    "type": "point",
    "toggle": true
  }
}

Такой режим критичен для интерфейсов с множественным выбором категорий.

Encoding selection через производные поля

Selection может быть преобразован в вычисляемые поля данных:

"transform": [
  {
    "calculate": "indata('sel_store', 'value', datum.category)",
    "as": "selected"
  }
]

Это позволяет интегрировать selection в обычный dataflow как переменную.

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

Selection хранится не как список DOM-объектов, а как компактное состояние:

  • множества значений,
  • диапазоны чисел,
  • пары координат,
  • битовые флаги.

Это обеспечивает:

  • O(1) проверку принадлежности,
  • отсутствие зависимости от рендера,
  • интеграцию в поток вычислений.

Композиция selection

В сложных визуализациях selection становится компонуемым элементом:

  • один selection управляет фильтрацией,
  • другой управляет подсветкой,
  • третий — масштабом.

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

"selection": {
  "brush": {"type": "interval"},
  "highlight": {"type": "point"}
}

Каждый слой взаимодействия работает независимо, но влияет на общую систему через dataflow.

Итоговая модель поведения selection

Selection можно формализовать как тройку:

  • состояние S (выбранные значения),
  • события E (изменения состояния),
  • функции отображения F (влияние на визуализацию).

S ← E → F

Эта модель делает selection универсальным механизмом связывания пользовательского взаимодействия и декларативного описания визуальных структур в Vega-Lite и Vega.