Сигналы
Сигналы — динамические переменные, задающие параметры визуализации и управляющие её интерактивностью. Сигналы можно использовать в разных частях спецификации Vega, например для задания свойства примитива или параметра преобразования данных.
Значения сигналов реактивны: они могут изменяться при поступлении событий ввода, вызовах внешнего API или изменении других сигналов. Потоки событий собирают и упорядочивают события ввода, например mousedown и touchmove. При возникновении события связанные с ним сигналы вычисляются заново в порядке их определения в спецификации. Затем новые значения передаются остальным частям спецификации, и визуализация автоматически перерисовывается.
Пример определения сигнала и его использования в спецификации:
{
"signals": [
{
"name": "indexDate",
"description": "Дата, которая обновляется при перемещении указателя мыши.",
"update": "datetime(2005, 0, 1)",
"on": [{"events": "mousemove", "update": "invert('x', x())"}]
}
],
"data": [
{ "name": "stocks", ... },
{
"name": "index",
"source": "stocks",
"transform": [
{
"type": "filter",
"expr": "month(datum.date) === month(indexDate)"
}
]
}
],
"scales": [
{ "name": "x", "type": "time", ... }
],
"marks": [
{
"type": "rule",
"encode": {
"update": {
"x": {"scale": "x", "signal": "indexDate"}
}
}
}
]
}
Свойства сигнала
При определении сигнала можно использовать следующие свойства.
| Свойство | Тип | Описание |
|---|---|---|
| name | String | Обязательно. Уникальное имя сигнала. Оно должно быть допустимым идентификатором JavaScript: содержать только буквы, цифры, $ или _ и не начинаться с цифры. Зарезервированные имена "datum", "event", "item" и "parent" использовать нельзя. |
| bind | Привязка | Привязывает сигнал к элементу ввода, например ползунку, раскрывающемуся списку или группе переключателей. |
| description | String | Текстовое описание сигнала для документации внутри спецификации. |
| on | Обработчик[ ] | Массив обработчиков потоков событий, обновляющих значение сигнала при событиях ввода. |
| init | Выражение | ≥ 4.4 Выражение для инициализации значения сигнала. Вычисляется только один раз. Свойства init и update взаимоисключающие. |
| update | Выражение | Выражение для обновления значения сигнала. Оно может ссылаться на другие сигналы; тогда значение обновляется при их изменении, если свойство react не равно false. Свойства init и update взаимоисключающие. |
| react | Boolean | Логический признак, определяющий, нужно ли автоматически пересчитывать выражение update при изменении связанных сигналов. По умолчанию true. Если задано false, зависимости от других сигналов не регистрируются даже при инициализации. |
| value | Any | Начальное значение сигнала (по умолчанию undefined). Присваивается до вычисления выражения init или update. |
Встроенные сигналы
Некоторые имена сигналов обрабатываются автоматически или зарезервированы:
- Сигналы для свойств спецификации
width,height,padding,autosize, а начиная с версии ≥ 5.10 иbackground, определяются автоматически. Их можно также определить в массивеsignalsверхнего уровня. В этом случае определения объединяются со значениями одноимённых свойств спецификации, причём приоритет имеют свойства из массиваsignals. - Экземпляры групповых примитивов автоматически содержат сигнал
parent, связанный с объектом данных группы. Определять в спецификации сигнал с именемparentнельзя. - Имена
datum,itemиeventзарезервированы для переменных верхнего уровня в выражениях. Определять сигналы с этими именами нельзя. - Если определить сигнал
cursor, его значение будет управлять CSS-видом указателя мыши в представлении Vega. Подробнее см. описание сигналаcursorниже.
Сигнал cursor
По умолчанию Vega меняет вид указателя мыши, когда он находится над примитивом со свойством cursor. Но при некоторых взаимодействиях курсор должен сохранять свой вид до их завершения: например, во время перетаскивания, даже если указатель ушёл с исходного примитива. Для этого служит отдельный сигнал cursor. Если ему задано значение, Vega использует его вместо свойств cursor отдельных примитивов. Значение "default" возвращает управление курсором свойствам примитивов.
Вложенные сигналы
Сигналы можно определять на верхнем уровне спецификации или внутри группового примитива. Сигнал, определённый во вложенной группе, доступен только в её области видимости: все примитивы, оси, легенды и другие элементы, которые на него ссылаются, должны находиться внутри этой группы. Если имя вложенного сигнала совпадает с именем сигнала во внешней области видимости, вложенное определение переопределяет внешнее.
Помимо новых определений, вложенный групповой примитив может содержать обновления сигналов из внешней области видимости. Свойство "push": "outer" означает, что обновление относится к уже существующему сигналу, а не создаёт новый. Во вложенном обновлении сигнала нельзя использовать свойства value и update. Доступны следующие свойства:
| Свойство | Тип | Описание |
|---|---|---|
| name | String | Обязательно. Имя обновляемого сигнала. |
| push | String | Обязательно. Для обновления сигнала из внешней области видимости свойству push нужно присвоить "outer". |
| description | String | Текстовое описание сигнала для документации. |
| on | Обработчик[ ] | Массив обработчиков потоков событий, обновляющих значение сигнала при событиях ввода. |
Обработчики событий
Объект обработчика содержит определение потока событий, задающее обрабатываемые события, а также выражение update для нового значения сигнала либо набор свойств кодирования encode для обновления примитива, с которым взаимодействует пользователь.
| Свойство | Тип | Описание |
|---|---|---|
| events | Поток событий | Обязательно. События, на которые реагирует обработчик. |
| update | Выражение | Выражение, вычисляемое при возникновении события. Его результат становится новым значением сигнала. Свойство обязательно, если не указано encode. |
| encode | String | Имя набора свойств кодирования примитива, который нужно пересчитать для элемента, вызвавшего событие ввода. Свойство обязательно, если не указано update. |
| force | Boolean | Логический признак (по умолчанию false), определяющий, нужно ли передавать обновления, которые не изменяют значение сигнала. При true зависимые сигналы получат уведомление, даже если событие установит прежнее значение. |
Этот сигнал увеличивает своё значение при событии mouseover на элементах rect:
{
"name": "count",
"value": 0,
"on": [
{"events": "rect:mouseover", "update": "count + 1"}
]
}
Этот сигнал применяет специальные наборы свойств кодирования при событиях mousedown и mouseup на элементах примитивов. Определение примитива должно содержать наборы "select" и "release" в свойстве "encode".
{
"name": "clickEncode",
"on": [
{"events": "*:mousedown", "encode": "select"},
{"events": "*:mouseup", "encode": "release"}
]
}
Привязка к элементу ввода
Свойство bind привязывает сигнал к элементу ввода вне визуализации. Vega создаёт элементы HTML-формы и устанавливает двустороннюю связь: изменение элемента обновляет сигнал, а изменение сигнала — элемент. Предусмотрена поддержка типов checkbox (флажок с логическим значением), radio (группа переключателей), select (раскрывающийся список) и range (ползунок). Сигнал также можно привязать к существующему внешнему элементу.
| Свойство | Тип | Описание |
|---|---|---|
| input | String | Обязательно. Тип элемента ввода: checkbox, radio, range, select или любой другой допустимый тип элемента HTML-формы. |
| element | String | Необязательный CSS-селектор родительского элемента, в который нужно добавить элемент ввода. По умолчанию элементы ввода добавляются в родительский контейнер представления Vega. |
| name | String | По умолчанию элемент ввода подписывается именем сигнала. Свойство name позволяет задать для связанного сигнала другую подпись. |
| debounce | Number | Если задано, откладывает обработку события до истечения указанного числа миллисекунд после последнего события. |
Свойства элементов radio и select
| Свойство | Тип | Описание |
|---|---|---|
| options | Array | Обязательно. Массив вариантов для выбора. |
| labels | String[ ] | ≥ 5.9 Массив подписей для значений options. Если не задан, значение options преобразуется в строку и используется как подпись. |
| name | String | По умолчанию элемент ввода подписывается именем сигнала. Свойство name позволяет задать другую подпись. |
| debounce | Number | Если задано, откладывает обработку события до истечения указанного числа миллисекунд после последнего события. |
Свойства элемента range
| Свойство | Тип | Описание |
|---|---|---|
| max | Number | Максимальное значение ползунка range. По умолчанию — большее из значения сигнала и 100. |
| min | Number | Минимальное значение ползунка range. По умолчанию — меньшее из значения сигнала и 0. |
| step | Number | Минимальный шаг ползунка range. Если не задан, шаг определяется автоматически по значениям min и max. |
| name | String | По умолчанию элемент ввода подписывается именем сигнала. Свойство name позволяет задать другую подпись. |
| debounce | Number | Если задано, откладывает обработку события до истечения указанного числа миллисекунд после последнего события. |
Другие типы элементов ввода
Свойству input можно присвоить любой допустимый тип элемента ввода HTML, например "text" (однострочное текстовое поле), "color" (выбор цвета) или "date" (ввод года, месяца и дня).
В этих случаях дополнительные свойства, например placeholder для "text", добавляются как атрибуты создаваемого элемента HTML-формы.
Прямая привязка к внешним элементам
Вместо создания нового элемента ввода Vega может привязать сигнал к уже существующему внешнему элементу. Для этого свойство input не задаётся, а свойство element ссылается на существующий элемент.
| Свойство | Тип | Описание |
|---|---|---|
| element | String | Обязательно. Элемент ввода со свойством value и поддержкой интерфейса EventTarget либо CSS-селектор такого элемента. Когда элемент изменяется и отправляет событие, значение value становится новым значением связанного сигнала. Когда сигнал изменяется независимо от элемента, его значение записывается в value, после чего на элементе отправляется новое событие. |
| event | String | Событие, по которому отслеживаются изменения внешнего элемента. По умолчанию "input". |
| debounce | Number | Если задано, откладывает обработку события до истечения указанного числа миллисекунд после последнего события. |