API представления
Представление (View) создаёт экземпляр графа потока данных Vega и отвечает за отрисовку визуализации и взаимодействие с ней. При инициализации в контейнере DOM оно добавляет на веб-страницу визуализацию на Canvas или SVG. Представление также можно использовать в браузере или на сервере для экспорта статических изображений SVG или PNG.
Справочник API представления
- Создание представления
- Настройка представления
- Поток данных и отрисовка
- Сигналы
- Обработка событий
- Экспорт изображений
- Данные и шкалы
Создание представления
Методы создания и завершения работы представления. Экземпляр View также наследует все непереопределённые методы родительского класса Dataflow.
# vega.View(runtime[, options]) Исходный код
Конструктор создаёт экземпляр View для описания потока данных Vega runtime. Необязательный объект options может содержать следующие свойства:
- background: цвет фона представления. См. метод background.
- bind: контейнер DOM или CSS-селектор для элементов ввода, привязанных к сигналам. См. метод initialize.
- container: родительский контейнер DOM или уникальный CSS-селектор представления. См. метод initialize.
- hover: логическое значение, включающее обработку наведения курсора. См. метод hover.
- loader: загрузчик файлов данных и изображений по умолчанию.
- logLevel: начальный уровень журналирования. См. метод logLevel.
- logger: начальный объект журнала. См. метод logger.
- renderer: тип рендерера (
'canvas'или'svg'). См. метод renderer. - tooltip: функция обработки всплывающих подсказок. См. метод tooltip.
- locale: определения локали для разбора строк и форматирования чисел и дат. Объект должен содержать свойства
numberи/илиtimeс определениями локали. Если свойство не задано, представление использует локаль, действовавшую по умолчанию при его создании. ≥ 5.12 - expr: альтернативный вычислитель выражений Vega. См. документацию по интерпретатору. ≥ 5.13
- watchPixelRatio: логическое значение, при котором изменение плотности пикселей страницы (например, из-за масштаба или смены монитора) запускает повторную отрисовку.
После конструктора обычно вызывают цепочку методов для настройки представления. Затем метод runAsync вычисляет граф потока данных, обновляет и отрисовывает визуализацию.
var view = new vega.View(runtime)
.logLevel(vega.Warn) // задать уровень журналирования
.renderer('svg') // выбрать рендерер (по умолчанию 'canvas')
.initialize('#view') // задать родительский элемент DOM
.hover(); // включить обработку наведения; вызывать только один раз!
view.runAsync(); // вычислить и отрисовать представление
Те же настройки можно передать конструктору View:
var view = new vega.View(runtime, {
logLevel: vega.Warn, // уровень журналирования
renderer: 'svg', // рендерер (по умолчанию 'canvas')
container: '#view', // родительский элемент DOM
hover: true // обработка наведения
});
view.runAsync(); // вычислить и отрисовать представление
Внутри функции async можно сразу дождаться результата:
var view = await new vega.View(runtime, {
logLevel: vega.Warn, // уровень журналирования
renderer: 'svg', // рендерер (по умолчанию 'canvas')
container: '#view', // родительский элемент DOM
hover: true // обработка наведения
}).runAsync(); // вычислить и отрисовать представление
# view.finalize() Исходный код
Подготавливает представление к удалению. Чтобы предотвратить нежелательное поведение и утечки памяти, метод отключает таймеры и удаляет обработчики событий, зарегистрированные в View или визуализацией на внешних элементах DOM. Вызывайте его, когда экземпляр больше не нужен.
Настройка представления
Методы настройки состояния представления. Обычно их вызывают сразу после конструктора View, до первого вызова runAsync или run.
# view.initialize([container, bindContainer]) Исходный код
Инициализирует отрисовку и обработку событий, затем возвращает текущий экземпляр представления. Если передан элемент DOM container, элементы визуализации (Canvas или SVG) добавляются внутрь него. Без container представление работает без отображения, но по-прежнему может создавать статические изображения методами экспорта. Необязательный элемент DOM или уникальный CSS-селектор bindContainer задаёт контейнер для элементов ввода, привязанных к сигналам. По умолчанию используется контейнер визуализации.
# view.loader([loader]) Исходный код
Возвращает или задаёт загрузчик файлов данных и изображений. Если заменить загрузчик после вызова initialize, визуализация инициализируется повторно. Если представление загружает данные по внешнему URL, запрос начинается сразу при создании экземпляра. Поэтому собственный загрузчик следует передавать в параметрах конструктора: вызов этого метода изменит его уже после первоначальных запросов. Метод сбрасывает рендерер; затем вызовите runAsync, чтобы обновить изображение.
# view.logLevel(level) Исходный код
Задаёт уровень журналирования и возвращает текущий экземпляр представления. Метод унаследован от Dataflow и определяет, какие сообщения выводятся в консоль JavaScript. Допустимые значения level: vega.None, vega.Error (по умолчанию), vega.Warn, vega.Info, vega.Debug. Подробнее см. метод logger пакета vega-util.
# view.logger(logger) Исходный код
Возвращает или задаёт объект журнала. Без аргумента возвращает текущий объект; с аргументом устанавливает новый и возвращает экземпляр View. Переданный объект должен поддерживать полный API журнала, создаваемого методом logger пакета vega-util. По умолчанию применяется уровень нового журнала; при необходимости измените его методом logLevel.
Методы собственного объекта журнала вызываются с представлением в качестве контекста this. Так журнал может получать дополнительные данные состояния View, например время текущего импульса. Методы, использующие внутреннее состояние журнала, должны избегать обращения к this; исключение — стрелочные функции, сохраняющие this из области, в которой они определены.
# view.renderer(type) Исходный код
Задаёт type рендерера ('canvas' по умолчанию или 'svg') и возвращает экземпляр представления. Обычно метод вызывают сразу после создания View, но тип можно изменить и позднее. Затем вызовите runAsync, чтобы обновить изображение.
Дополнительные рендереры можно зарегистрировать методом renderModule из vega-scenegraph. Пример такого расширения — vega-webgl-renderer.
# view.tooltip(tooltipHandler) Исходный код
Возвращает или задаёт функцию отображения всплывающих подсказок, например при наведении курсора на элемент. Метод сбрасывает рендерер; после его вызова используйте runAsync, чтобы обновить изображение. Функция tooltipHandler должна иметь следующую сигнатуру:
function(handler, event, item, value) {
// вывести подсказку собственным способом
}
Аргументы функции tooltipHandler:
- handler — экземпляр обработчика ввода графа сцены, вызвавший tooltipHandler.
- event — событие, вызвавшее обновление подсказки.
- item — элемент графа сцены, к которому относится подсказка.
- value — отображаемое значение.
nullилиundefinedозначает, что подсказка не нужна. Значение может иметь любой тип, включая объект и массив; его обработка и вывод возлагаются на tooltipHandler. - Vega вызывает tooltipHandler, передавая текущее представление как контекст
this.
Стандартный обработчик использует встроенные подсказки браузера: преобразует значение в строку и записывает её в HTML-атрибут "title" элемента, содержащего View. Простые значения преобразуются в строки, а содержимое объектов и массивов показывается на один уровень вложенности. У объекта каждая пара ключа и значения выводится с новой строки ("key1: value\nkey2: value2").
# view.hover([hoverSet, updateSet]) Исходный код
Включает обработку наведения курсора и возвращает экземпляр представления. Необязательные аргументы задают имена наборов кодирования для событий mouseover и mouseout. По умолчанию hoverSet равен 'hover', а updateSet — 'update'; им соответствуют наборы в блоке "encode" спецификации примитива Vega. Если метод не вызван, представление не обрабатывает наведение автоматически: для этого нужно явно настроить потоки событий в описании потока данных.
Вызывайте этот метод только один раз при инициализации представления. Повторные вызовы добавляют лишние обработчики событий: метод не идемпотентен.
# view.description([text]) Исходный код ≥ 5.10
Возвращает или задаёт описание представления text. Оно определяет атрибут aria-label контейнера. Без аргументов метод возвращает текущее описание, а с аргументом обновляет описание и элемент контейнера.
# view.background([color]) Исходный код
Возвращает или задаёт цвет фона представления. Без аргументов возвращает текущий цвет. Аргумент color переопределяет цвет из спецификации Vega и метод возвращает экземпляр представления. Изменение не отображается немедленно: когда нужно обновить визуализацию, вызовите runAsync. Метод эквивалентен view.signal('background'[, color]).
# view.width([width]) Исходный код
Возвращает или задаёт ширину представления в пикселях. Без аргументов возвращает текущую ширину. С аргументом width устанавливает новое значение и возвращает экземпляр представления. Изменение не отображается немедленно: когда нужно обновить визуализацию, вызовите runAsync. Метод эквивалентен view.signal('width'[, width]).
# view.height([height]) Исходный код
Возвращает или задаёт высоту представления в пикселях. Без аргументов возвращает текущую высоту. С аргументом height устанавливает новое значение и возвращает экземпляр представления. Изменение не отображается немедленно: когда нужно обновить визуализацию, вызовите runAsync. Метод эквивалентен view.signal('height'[, height]).
# view.padding([padding]) Исходный код
Возвращает или задаёт внутренние отступы представления в пикселях. Объект padding имеет вид {left: 5, top: 5, right: 5, bottom: 5}. Если передать число, оно применяется ко всем сторонам. Без аргументов метод возвращает текущие отступы; с аргументом — устанавливает их и возвращает экземпляр представления. Изменение не отображается немедленно: когда нужно обновить визуализацию, вызовите runAsync. Метод эквивалентен view.signal('padding'[, padding]).
# view.resize() Исходный код
Устанавливает признак повторного расчёта автоматического размера при следующем проходе потока данных. При режиме "pad" или "fit" границы диаграммы будут пересчитаны при следующем вызове runAsync.
Поток данных и отрисовка
Методы запуска вычисления потока данных и отрисовки представления.
# view.runAsync([encode, prerun, postrun]) Исходный код
Вычисляет граф потока данных и возвращает Promise, который выполняется после обработки данных и отрисовки графа сцены. Необязательный строковый аргумент encode задаёт имя дополнительного набора "encode", который выполняется вместе со стандартным "update". Изменённые при вычислении элементы графа сцены автоматически перерисовываются.
Внутри метод вызывает вычисление родительского класса Dataflow, затем выполняет отрисовку. Promise завершается после отрисовки. Не вызывайте метод повторно, пока не завершился предыдущий вызов: используйте await или цепочку .then(...).
Необязательные функции prerun и postrun вызываются непосредственно до и после вычисления потока данных и отрисовки. Единственным аргументом им передаётся экземпляр представления. Функции могут быть асинхронными. postrun выполняется после обработчиков, зарегистрированных через runAfter.
В большинстве приложений аргументы prerun и postrun не нужны. Они предназначены для внутренних операций Vega. Обычно действия после вычисления удобно выполнять через then или await для результата runAsync.
При потоковой передаче данных перед runAsync может быть полезно вызвать resize.
# view.run([encode, prerun, postrun]) Исходный код
Запускает асинхронное вычисление представления и сразу возвращает его экземпляр, не дожидаясь завершения. Аргументы совпадают с аргументами runAsync.
Метод возвращает результат раньше, чем завершится вычисление потока данных. Чтобы выполнить действия после вычисления, используйте runAsync и дождитесь возвращённого Promise через then или await.
# view.runAfter(callback) Исходный код
Планирует вызов функции callback после завершения текущего вычисления потока данных. Единственным аргументом ей передаётся экземпляр представления. Функция может быть асинхронной.
Если вычисление сейчас не выполняется, функция вызывается сразу. Внутри Vega метод планирует последующие операции потока данных. Большинству приложений он не нужен: используйте runAsync и выполняйте последующие действия после завершения Promise.
# view.dirty(item) Исходный код
Помечает элемент графа сцены как изменённый для повторной отрисовки после следующего вычисления потока данных. Обычно метод вызывают сами операторы потока данных для обновления списка элементов при поэтапной отрисовке.
# view.container() Исходный код
Возвращает элемент DOM контейнера представления, если он есть.
# view.scenegraph() Исходный код
Возвращает экземпляр графа сцены Vega для представления.
# view.origin() Исходный код
Возвращает координаты начала отсчёта [x, y] представления. Они задают смещение основной системы координат с учётом левого и верхнего отступов, а также дополнительных отступов, рассчитанных при автоматическом подборе размера.
Сигналы
Методы чтения и обновления значений сигналов потока данных.
# view.signal(name[, value]) Исходный код
Возвращает или задаёт сигнал потока данных. Если передан только name, возвращает значение сигнала. Если передан и value, обновляет сигнал и возвращает экземпляр представления. Отсутствующий сигнал вызывает ошибку. Изменение не отображается немедленно: когда нужно обновить визуализацию, вызовите runAsync.
# view.getState([options]) Исходный код
Возвращает состояние сигналов и наборов данных в графе потока данных представления. Без аргументов возвращает объект со значениями сигналов и изменёнными наборами данных. По умолчанию он содержит значения сигналов во всех областях примитивов, кроме связанных с преобразованиями данных, а также наборы данных, явно изменённые триггерами или через API View.
Аргумент options управляет составом сохраняемого внутреннего состояния. Он затрагивает внутреннее устройство потока данных Vega и предназначен для опытных разработчиков. Обычно достаточно настроек по умолчанию.
Объект options поддерживает следующие свойства:
- signals: функция-предикат, принимающая name сигнала и его operator; возвращает
true, если состояние оператора нужно экспортировать. - data: функция-предикат, принимающая name и объект набора данных; возвращает
true, если данные нужно экспортировать. - recurse: логическое значение, определяющее, нужно ли обходить вложенные области примитивов.
# view.setState(state) Исходный код
Устанавливает state сигналов и/или наборов данных в графе потока данных. Аргумент должен быть объектом, полученным методом getState. Метод обновляет соответствующие сигналы и данные, вызывает run и возвращает экземпляр представления.
# view.addSignalListener(name, handler) Исходный код
Регистрирует обработчик изменений сигнала name и возвращает экземпляр представления. Если сигнал не существует, возникает ошибка. Метод идемпотентен: повторная регистрация того же обработчика для того же сигнала ничего не меняет.
Когда значение сигнала меняется, функция handler получает два аргумента: имя сигнала name и новое value. Обработчики вызываются при изменении сигнала во время прохода потока данных, например после вызова runAsync, но до завершения его Promise.
Обработчик вызывается сразу после обновления сигнала, пока вычисление потока данных ещё идёт. Другие сигналы и преобразования в этот момент могут не успеть обновиться. Чтобы читать или менять их значения и повторно запускать поток данных, используйте runAsync с обработчиком prerun: нужные действия выполнятся после текущего вычисления, но до повторного запуска. Вызов синхронного метода run из обработчика сигнала приведёт к ошибке, поскольку рекурсивный запуск запрещён.
Чтобы удалить обработчик, вызовите removeSignalListener.
view.addSignalListener('width', function(name, value) {
console.log('WIDTH: ' + value);
});
view.width(500).run(); // обработчик выводит 'WIDTH: 500'
# view.removeSignalListener(name, handler) Исходный код
Удаляет обработчик сигнала, зарегистрированный через addSignalListener, и возвращает экземпляр представления. Если сигнала нет, возникает ошибка. Если сигнал есть, но указанный handler не зарегистрирован, ничего не происходит.
Обработка событий
Методы создания потоков событий, регистрации обработчиков и управления подсказками. См. также метод hover.
# view.events(source, type[, filter]) Исходный код
Возвращает новый EventStream для источника source, типа события type и необязательной функции filter. Источник может быть строкой "view" (текущее представление), "window" (окно браузера) или допустимым CSS-селектором, который передаётся document.querySelectorAll. type должен быть допустимым типом события DOM. Функция filter принимает объект события и возвращает true, если его нужно включить в поток.
Обычно Vega вызывает метод внутри системы для создания потоков, упомянутых в определениях сигналов. Приложение тоже может создавать собственные потоки событий. Метод рассчитан на работу в браузере; в другой среде он может не дать результата.
# view.addEventListener(type, handler[, options]) Исходный код
Регистрирует обработчик входных событий и возвращает экземпляр представления. Строковый type должен обозначать допустимое событие DOM, поддерживаемое обработчиками vega-scenegraph, например "mouseover", "click", "keydown" или "touchstart". Метод идемпотентен: повторная регистрация того же обработчика для того же события ничего не меняет.
Необязательный объект options поддерживает свойство options.trap. Значение false отключает автоматический перехват ошибок в обработчиках событий.
При событии функция handler получает два аргумента: объект event и активный элемент графа сцены item. Если целью события является само представление, item равен null.
При смене рендерера все зарегистрированные обработчики сохраняются. Например, если renderer изменить с "canvas" на "svg", они продолжат работать. Для удаления используйте removeEventListener.
view.addEventListener('click', function(event, item) {
console.log('CLICK', event, item);
});
# view.removeEventListener(type, handler) Исходный код
Удаляет обработчик события, зарегистрированный через addEventListener, и возвращает экземпляр представления.
# view.addResizeListener(handler) Исходный код
Регистрирует обработчик изменения размера представления и возвращает его экземпляр. Метод идемпотентен: повторная регистрация того же обработчика ничего не меняет.
При изменении размера функция handler получает два аргумента: ширину width и высоту height представления.
view.addResizeListener(function(width, height) {
console.log('RESIZE', width, height);
});
# view.removeResizeListener(handler) Исходный код
Удаляет обработчик, зарегистрированный через addResizeListener, и возвращает экземпляр представления.
# view.globalCursor(flag) Исходный код ≥ 5.13
Возвращает или задаёт логический признак flag (по умолчанию false), определяющий область изменения курсора: весь документ при true или только компонент View при false. Значение метода имеет приоритет над настройкой курсора в спецификации Vega.
# view.preventDefault(flag) Исходный код
Возвращает или задаёт логический признак flag (по умолчанию false), определяющий, будет ли Vega вызывать preventDefault() для входных событий. Метод задаёт лишь поведение по умолчанию; настройки событий в спецификации или парсере имеют приоритет.
Экспорт изображений
Методы экспорта статических изображений визуализации. Их можно вызывать в браузере и на сервере.
# view.toCanvas([scaleFactor, options]) Исходный код
Возвращает Promise с экземпляром Canvas, содержащим растровое изображение представления. Необязательный scaleFactor (по умолчанию 1) умножает ширину и высоту выходного изображения. В браузере результатом будет элемент HTML5 Canvas, а в Node.js — экземпляр Canvas пакета node-canvas.
Необязательный объект options задаёт дополнительные параметры Canvas:
- type: строка типа, передаваемая конструктору Canvas в
node-canvas, например'pdf'для PDF. В браузере свойство игнорируется. - context: объект свойств и значений для двумерного контекста Canvas. Особенно полезен при работе с
node-canvas. - externalContext: внешний экземпляр
Context2Dдля отрисовки. Если он передан,Promiseметода toCanvas возвращаетnull. Vega меняет состояние контекста; перед toCanvas() вызовите context.save(), а после выполненияPromiseвосстановите состояние через context.restore(). ≥ 5.12
# view.toSVG([scaleFactor]) Исходный код
Возвращает Promise со строкой SVG — векторным изображением представления. Необязательный scaleFactor (по умолчанию 1) умножает ширину и высоту выходного изображения.
# view.toImageURL(type[, scaleFactor]) Исходный код
Возвращает Promise с URL снимка текущего представления. Аргумент type должен быть равен 'svg', 'png' или 'canvas'; последние два варианта создают PNG. Полученный URL можно использовать для сохранения изображения. Необязательный scaleFactor (по умолчанию 1) умножает ширину и высоту выходного изображения.
// создать снимок PNG и сохранить изображение
view.toImageURL('png').then(function(url) {
var link = document.createElement('a');
link.setAttribute('href', url);
link.setAttribute('target', '_blank');
link.setAttribute('download', 'vega-export.png');
link.dispatchEvent(new MouseEvent('click'));
}).catch(function(error) { /* обработка ошибки */ });
Данные и шкалы
Методы доступа к шкалам и наборам данных, а также потокового обновления данных.
# view.scale(name) Исходный код
Возвращает экземпляр шкалы или проекции с именем name. Это рабочий объект, который использует поток данных. Не изменяйте его напрямую!
# view.data(name[, values]) Исходный код
Если передан один аргумент, возвращает набор данных name. Возвращаемый массив объектов — рабочий массив потока данных. Если его нужно изменить, сначала создайте копию, например через view.data('name').slice().
≥ 5.5 Если переданы два аргумента, удаляет текущие данные и вставляет values: отдельный объект или массив объектов. Вызов эквивалентен следующему:
view.change(name, vega.changeset().remove(vega.truthy).insert(values));
Обновление данных не перерисовывает представление сразу: когда нужно, вызовите runAsync. Вызов с одним аргументом возвращает выход цепочки преобразований, а с двумя задаёт её вход.
# view.addDataListener(name, handler) Исходный код
Регистрирует обработчик изменений набора данных name и возвращает экземпляр представления. Если набора нет, возникает ошибка. Метод идемпотентен: повторная регистрация того же обработчика для того же набора ничего не меняет.
При изменении набора данных функция handler получает его имя name и новое значение value. Обработчики вызываются во время прохода потока данных, например после runAsync, но до завершения его Promise. Переданное значение совпадает с результатом view.data и представляет собой рабочий массив. Прежде чем менять его, создайте копию, например через value.slice().
Обработчик вызывается сразу после обновления набора, пока вычисление потока данных ещё идёт. Другие сигналы и преобразования могут не успеть обновиться. Чтобы читать или менять другие сигналы и повторно запускать поток данных, используйте runAsync с обработчиком prerun: нужные действия выполнятся после текущего вычисления, но до повторного запуска. Вызов run из обработчика приведёт к ошибке, поскольку рекурсивный запуск запрещён.
Чтобы удалить обработчик, вызовите removeDataListener.
view.addDataListener('source', function(name, value) {
console.log(name, value);
});
# view.removeDataListener(name, handler) Исходный код
Удаляет обработчик набора данных, зарегистрированный через addDataListener, и возвращает экземпляр представления. Если набора нет, возникает ошибка. Если набор есть, но указанный handler не зарегистрирован, ничего не происходит.
# view.change(name, changeset) Исходный код
Обновляет набор данных name по переданному объекту изменений changeset. Метод не перерисовывает представление сразу: когда нужно, вызовите runAsync. При серии изменений, вставок и удалений дожидайтесь завершения каждого runAsync через await перед следующей операцией.
view.change('data', vega.changeset().insert([...]).remove([...]))
.run()
Методы insert и remove объекта changeset принимают по одному аргументу. Допустимые значения совпадают со вторыми аргументами методов view.insert и view.remove.
Вставляемые записи данных должны быть заранее разобранными объектами JavaScript. Правила "format" из источника данных спецификации Vega не применяются к записям, добавленным через API View. Внутри метод передаёт ChangeSet вызову Dataflow.pulse; подробности — в vega-dataflow.
Начиная с версии ≥ 5.13, changeset также поддерживает необязательный логический параметр clean, определяющий, следует ли Vega выполнять внутреннюю сборку мусора после изменения. Если изменение удаляет данные, значение по умолчанию — true.
# view.insert(name, tuples) Исходный код
Вставляет массив новых записей tuples в набор данных name и возвращает экземпляр представления. Массив должен содержать один или несколько объектов, которых ещё нет в наборе. Метод не перерисовывает представление сразу: когда нужно, вызовите runAsync.
В одном проходе потока данных нельзя сочетать insert и remove. Для одновременного добавления и удаления используйте change. При серии операций дожидайтесь завершения runAsync через await перед следующим изменением.
Вставляемые записи должны быть заранее разобранными объектами JavaScript. Правила "format" из источника данных спецификации Vega не применяются к записям, добавленным через API View. Внутри метод создаёт ChangeSet и вызывает Dataflow.pulse; подробности — в vega-dataflow.
# view.remove(name, tuples) Исходный код
Удаляет записи tuples из набора данных name и возвращает экземпляр представления. Аргумент tuples может быть массивом существующих записей или функцией-предикатом, определяющей, какие записи удалить. Метод не перерисовывает представление сразу: когда нужно, вызовите runAsync.
В одном проходе потока данных нельзя сочетать remove и insert. Для одновременного добавления и удаления используйте change. При серии операций дожидайтесь завершения runAsync через await перед следующим изменением.
Например, так можно удалить из набора 'table' все записи со свойством count меньше пяти:
view.remove('table', d => d.count < 5).run();
Внутри метод создаёт ChangeSet и вызывает Dataflow.pulse; подробности — в vega-dataflow.