В библиотеке Vega ключевой объект исполнения визуализаций —
View. Он представляет собой активный экземпляр
спецификации, в котором происходит рендеринг сценографа, обработка
сигналов, вычисление данных и управление взаимодействиями.
View выступает мостом между декларативным описанием
графика и реальной DOM/Canvas-сценой. Любое интерактивное поведение —
клики, наведение, перетаскивание, выделение — проходит через событийную
систему этого объекта.
Событийная модель View построена вокруг регистрации
обработчиков через addEventListener. Она не ограничивается
только DOM-событиями, а расширяет их за счёт:
Основная идея заключается в том, что визуализация рассматривается как реактивная система, где любое действие пользователя или изменение состояния может быть перехвачено и обработано.
Базовая форма регистрации обработчика:
view.addEventListener(type, handler)
type — строка, определяющая тип события. handler — функция обратного вызова, вызываемая при возникновении события.
function handler(event, item) {
// event — объект события
// item — элемент сцены (если применимо)
}
В зависимости от типа события структура аргументов может варьироваться, однако основной объект события содержит всю необходимую информацию о контексте взаимодействия.
Событийная система Vega включает несколько категорий событий, которые
могут быть перехвачены через addEventListener.
Наиболее часто используемая группа событий:
clickdblclickmousedownmouseupmouseovermouseoutmousemovewheelПример:
view.addEventListener('click', function(event, item) {
console.log('Клик по элементу:', item);
});
События мыши связаны с элементами сценографа, поэтому
item часто содержит информацию о визуальном примитиве
(mark), данных и вычисленных значениях.
Для сенсорных устройств:
touchstarttouchmovetouchendview.addEventListener('touchstart', (event, item) => {
console.log('Начало касания');
});
keydownkeyupЭти события обрабатываются на уровне всего View, а не
отдельных графических элементов:
view.addEventListener('keydown', function(event) {
if (event.key === 'Escape') {
console.log('Сброс состояния');
}
});
Внутренние события рендеринга и взаимодействия:
render — завершение отрисовкиbeforeRender — перед отрисовкойresize — изменение размеров viewview.addEventListener('resize', function(event) {
console.log('Размеры обновлены');
});
Хотя чаще используются специализированные методы
(addDataListener, addSignalListener), часть
системных событий может быть доступна через
addEventListener:
Объект event содержит контекст взаимодействия и является
центральным элементом обработки.
Типичная структура:
{
type: "click",
x: 120,
y: 80,
item: { /* описание mark */ },
timestamp: 1710000000000,
event: MouseEvent
}
type Строка, тип события.
x, y Координаты в системе координат view.
item Ссылка на элемент сцены:
event Оригинальный DOM-событие (MouseEvent, KeyboardEvent).
Одним из ключевых сценариев является извлечение данных из визуального элемента:
view.addEventListener('click', function(event, item) {
if (item && item.datum) {
console.log('Данные точки:', item.datum);
}
});
datum — это исходная запись данных, привязанная к
визуальному элементу.
События часто используются для реализации взаимодействий:
let selected = null;
view.addEventListener('click', function(event, item) {
selected = item.datum;
view.signal('selectedPoint', selected).run();
});
Здесь происходит связка событийной модели и системы сигналов.
view.addEventListener('mouseover', function(event, item) {
view.signal('hovered', item.datum).run();
});
view.addEventListener('mouseout', function() {
view.signal('hovered', null).run();
});
Сигналы в Vega представляют реактивные переменные, которые управляют состоянием визуализации.
Связка событий и сигналов позволяет строить интерактивные системы:
view.addSignalListener('selection', function(name, value) {
console.log('Сигнал изменён:', value);
});
Комбинация событий и сигналов создаёт двустороннюю модель:
Для управления жизненным циклом взаимодействий предусмотрен метод:
view.removeEventListener(type, handler)
Важно сохранять ссылку на функцию:
function onClick(event, item) {
console.log(item);
}
view.addEventListener('click', onClick);
view.removeEventListener('click', onClick);
Без сохранённой ссылки удаление невозможно.
События обрабатываются после построения сцены, что позволяет получать актуальные позиции элементов.
В Vega события не привязаны к отдельным DOM-узлам, а проходят через сценограф:
Чрезмерное количество обработчиков может влиять на:
Оптимизация достигается через:
В Vega-Lite работа с событиями чаще абстрагируется через
декларативные конструкции selection.
Однако при компиляции Vega-Lite в Vega создаётся полноценный
View, где addEventListener становится
доступным на уровне результирующей спецификации.
Типичный сценарий:
При расширении визуализации кастомной логикой события используются для:
view.addEventListener('brush', function(event) {
const range = event.selection;
console.log('Выделенный диапазон:', range);
});
Один тип события может иметь несколько независимых обработчиков:
view.addEventListener('click', handlerA);
view.addEventListener('click', handlerB);
Порядок выполнения не гарантируется, что требует аккуратного проектирования взаимодействий.
Для диагностики поведения часто используется логирование:
view.addEventListener('*', function(event) {
console.log(event);
});
Хотя wildcard-события не всегда поддерживаются напрямую, аналогичный эффект достигается через регистрацию на ключевые типы событий.