Переход с Vega 2

В этом руководстве описаны изменения, необходимые для переноса спецификаций Vega 2.x в новые версии. Также здесь представлены некоторые возможности Vega 3. Перечень охватывает основные различия между версиями; дополнительные варианты использования показаны в галерее примеров.

Содержание руководства

Примитивы и визуальное кодирование

  • Блок визуального кодирования "properties" переименован в "encode".

  • Директива кодирования "signal" теперь принимает не только имена сигналов, но и выражения. Это позволяет задавать визуальное кодирование напрямую, например {"signal": "datum.field * 2"}.

  • Директива "template" удалена. Для аналогичной обработки текста используйте выражение в директиве "signal".

  • Свойства кодирования "mult" и "offset" поддерживают вложенные директивы, что даёт больше возможностей настройки. Например, "x": {"scale": "xscale", "field": "foo", "offset": {"scale": "oscale", "field": "bar"}}.

  • Свойство "band" принимает долю от 0 до 1 для размещения элемента внутри полосы шкалы и может сочетаться с отображением поля на шкалу. Например, {"scale": "xscale", "field": "foo", "band": 0.5} располагает элемент в середине соответствующей полосы.

  • Примитив rule поддерживает произвольные отрезки и надёжно проводит линию от точки "x", "y" до "x2", "y2".

  • Определения примитивов больше не допускают встроенные преобразования данных (например, {"type": "rect", "from": {"data": "table", "transform": [...]}}). Теперь все производные источники следует определять в блоках "data". При этом начиная с Vega 3 блок "data" можно размещать не только на верхнем уровне спецификации, но и внутри примитива group. Так можно создавать производные наборы данных внутри группы фасетов.

  • Преобразование "facet" больше не поддерживается. Вместо него в блоке "from" примитива применяется одноимённая директива для различных способов фасетирования. Для группировки также можно использовать преобразование "aggregate". Например, в спецификации barley.vg.json группа разбивается на фасеты так:

    "from": {
      "facet": {
        "name": "sites",
        "data": "barley",
        "groupby": "site"
      }
    },
    

    Вложенные примитивы обращаются к данным фасета по имени: "from": {"data": "sites"}. Блок "facet" также принимает параметры преобразования "aggregate" для создания элементов данных внутри group. Кроме того, Vega 3 поддерживает заранее подготовленные фасеты, когда запись данных содержит вложенный набор записей. Такие группы можно сформировать вне Vega и передать напрямую:

    "from": {
      "facet": {
        "name":  "facets",
        "data":  "input", // [{children: [...]}, {children: [...]}]
        "field": "children"
      }
    },
    

    В этом случае каждая запись набора input создаёт элемент примитива group, а соответствующая группа содержит записи из поля "children".

  • Помимо блока "encode" (ранее "properties"), определения примитивов поддерживают преобразования после кодирования. Они выполняются после "encode" и напрямую читают и записывают свойства элементов графа сцены. Например, алгоритмы размещения — силовой, облако слов или дерево — могут сразу задавать визуальные свойства вместо записи в промежуточную строку данных и последующего копирования, как в Vega 2. После кодирования допускаются только преобразования, которые не фильтруют и не создают записи. Фрагмент wordcloud.vg.json:

    "marks": [{
      "type": "text",
      "from": {"data": "table"},
      "encode": {...},
      "transform": [
        {
          "type": "wordcloud",
          "size": [800, 400],
          "text": {"field": "text"},
          ...
        }
      ]
    }]
    
  • В Vega 3 появился примитив shape, похожий на path. Но path требует заранее созданную строку пути SVG, а shape формируется процедурно: рендереру передаётся функция рисования контура. Это избавляет Canvas-рендерер от промежуточной строки пути и может заметно ускорить отрисовку. При использовании SVG строка пути всё же создаётся, но во время отрисовки, а не визуального кодирования.

  • В Vega 3 добавлен zindex для управления порядком слоёв соседних элементов. Его значение — неотрицательное целое число; по умолчанию оно равно нулю. Чем выше значение, тем выше элемент расположен относительно соседних примитивов. Свойство "zindex" допустимо в определениях примитивов, осей и легенд, а также в отдельных наборах кодирования, например "hover" и "update". Сортировка работает только среди соседних элементов: отдельный элемент одного набора примитивов нельзя таким способом поднять над элементами другого набора.

К содержанию

Сигналы и обработка событий

  • Свойство сигнала "streams" переименовано в "on". В описании потока событий параметр "type" стал "events", а "expr" — "update". Например, вместо {"name": "foo", "streams": [{"type": "rect:mousedown", "expr": "eventX()"}]} теперь пишут {"name": "foo", "on": [{"events": "rect:mousedown", "update": "x()"}]}.

  • Параметр "events" в описании потока может быть строкой селектора событий, как в Vega 2.x, или структурированным объектом JSON.

  • Функции выражений eventItem, eventGroup, eventX и eventY заменены более короткими item, group, x и y. Новая функция xy возвращает текущие координаты указателя массивом [x, y].

  • По умолчанию Vega больше не подавляет события через event.preventDefault(). Чтобы отменить стандартное поведение браузера для события, добавьте в селектор восклицательный знак после имени события, например {"events": "window:mousemove!"}.

  • Флаг "verbose" переименован в "force" и теперь задаётся для отдельных элементов массива "on". Например, вместо {"name": "clickedPoint", "verbose": true, "streams": [{"type": "click", "expr": "datum.key"}]} используется {"name": "clickedPoint", "on": [{"events": "click", "update": "datum.key", "force": true}]}.

  • Для инициализации сигнала вместо "init" используются "value" с буквальным значением или "update" с выражением.

  • В определении сигнала появилось свойство "bind", связывающее его значение с автоматически созданным элементом ввода HTML. Так можно добавлять к интерактивной визуализации внешние элементы управления. Синтаксис "bind" следует прежней модели vega-embed; примеры — airports.vg.json и map-bind.vg.json.

  • Изменился API View для обработчиков событий. Методы view.on и view.off удалены. Для обычных обработчиков используйте view.addEventListener и view.removeEventListener, а для экземпляров EventStream — новый view.events.

  • В API View изменились обработчики сигналов: вместо view.onSignal и view.offSignal используйте view.addSignalListener и view.removeSignalListener.

К содержанию

Размещение представления

  • Свойство верхнего уровня "viewport" из Vega 2.x удалено. Аналогичное поведение задаётся CSS-свойствами width, height и overflow контейнера DOM представления Vega.

  • Свойства диаграммы "width" и "height" автоматически связаны с одноимёнными сигналами. Их можно не указывать на верхнем уровне спецификации, а определить сигналы с выражениями "update", динамически задающими ширину и высоту.

  • В Vega 3 появилось свойство верхнего уровня "autosize" для выбора режима размещения. Допустимые значения:
    • "pad" (по умолчанию) — ширина и высота задают прямоугольник данных. Для осей и легенд выделяется дополнительное место. Аналог "padding": "auto" в Vega 2.
    • "fit" — ширина и высота задают итоговый размер без явных отступов. Сигналы размеров автоматически меняются, чтобы вместить оси и легенды. Если места не хватает, элементы могут обрезаться. Аналог "padding": "strict" в Vega 2.
    • "none" — автоматическая подгонка не выполняется. Итоговый размер равен сумме ширины или высоты с соответствующими явными отступами. Возможно обрезание.
  • В Vega 3 у свойства "padding" удалены варианты "auto" и "strict". Теперь оно всегда задаёт фиксированные отступы вокруг визуализации. При "autosize": "pad" они добавляются к результату автоматического расчёта размера.

  • SVG-рендерер поддерживает базовое адаптивное изменение размера. Создаваемый SVG содержит атрибут viewBox, поэтому при изменении размера элемента его содержимое масштабируется вместе с ним.

К содержанию

Оси и легенды

  • У осей больше нет параметра type; вместо него требуется orient. Замените {"type": "x"} на {"orient": "bottom"}, а {"type": "y"} — на {"orient": "left"}.

  • Параметр приблизительного числа делений оси "ticks" переименован в "tickCount".

  • Пользовательские визуальные свойства осей и легенд теперь располагаются в блоке "encode" с подразделами "enter", "update" и "exit". Если выбор неочевиден, используйте "update", чтобы свойства обновлялись всегда.

  • В пользовательском блоке "encode" оси или легенды можно задать логическое свойство "interactive": оно определяет, реагируют ли отдельные элементы на ввод. Например, так включается взаимодействие с символами легенды:

    "legends": [
      {
        "fill": "colorScale",
        "title": "Заголовок легенды",
        "orient": "right",
        "encode": {
          "symbols": {
            "interactive": true,
            "hover": {...},
            "update": {...}
          }
        }
      }
    ]
    
  • У легенд появилось необязательное свойство "type". По умолчанию используется "symbol" для дискретной легенды. Для непрерывной цветовой шкалы можно выбрать "gradient" с цветовым градиентом. См. пример legends.vg.json.

  • Свойство оси "layer" удалено; вместо него используется "zindex" (по умолчанию 0). Обычно ось рисуется позади элементов диаграммы. Чтобы вывести её вперёд, задайте "zindex": 1.

  • Линия оси, ранее оформлявшаяся через "axis", теперь называется "domain". Чтобы скрыть её, задайте "domain": false; для настройки вида добавьте свойство "domain" в блок "encode".

  • Деления, подписи, линии сетки и линию оси можно включать независимо. Деления, подписи и линия оси включены по умолчанию, но отключаются, например, через "ticks": false или "labels": false. Сетка по умолчанию выключена; её включает "grid": true. Так можно строить сложные слои: разместить ось только с сеткой сзади, а другую — с делениями и подписями спереди.

  • По умолчанию протяжённость линий сетки определяется сигналами "width" (для вертикальной оси) или "height" (для горизонтальной). В Vega 2 использовались размеры группы. В Vega 3 значения именованных сигналов можно переопределять во вложенных группах, чтобы задать размеры отдельных областей. Также появилось свойство "gridScale": оно указывает шкалу, диапазон которой определяет длину линий сетки. Если шкала по x называется "xscale", длину линий сетки оси y можно задать через "gridScale": "xscale".

К содержанию

Шкалы

  • По образцу D3 4.0 прежний тип шкалы "ordinal" разделён на три: "ordinal" для таблиц соответствий, "band" для пространственных порядковых шкал и "point" для таких шкал без полос (аналог {"point": true} в Vega 2).

  • В Vega 3 добавлен тип шкалы "sequential" из D3 4.0+ и соответствующие цветовые шкалы. Свойство "scheme" задаёт именованную палитру, например "viridis", "plasma" или "magma". Список встроенных схем и способ добавления своих приведены в документации цветовых схем.

  • Палитры "category10", "category20" и подобные больше не являются встроенными именами диапазонов. Они доступны через свойство шкалы "scheme", которое заменяет диапазон у шкал "ordinal" и "sequential". Для порядковых шкал Vega 3 также предоставляет сокращение "category"; его можно переопределить в конфигурации темы.

  • В Vega 3 появился тип шкалы "index", сопоставляющий порядковую область определения с количественным диапазоном, как у "linear" или "sequential". Это удобно для упорядоченных цветовых градиентов категориальных данных.

  • Если область определения шкалы строится по нескольким полям одной таблицы, их нужно перечислить в "fields", а не в "field", например "domain": {"data": "table", "fields": ["fieldA", "fieldB"]}.

К содержанию

Преобразования данных

  • В Vega 3 добавлены новые преобразования и улучшены существующие, в том числе существенно улучшенное преобразование "force" и поддержка иерархического размещения. Многие показаны в спецификациях из галереи примеров. Параметры каждого преобразования также описаны в комментариях JSDoc его исходного кода.

  • Объекты "output", задававшие имена выходных полей преобразований в Vega 2.x, удалены. Соответствующие преобразования принимают параметр "as": в зависимости от типа это строка или упорядоченный массив строк с нужными именами полей. Подробности приведены на страницах отдельных преобразований и в комментариях JSDoc исходного кода.

  • Аналогично параметр "field" преобразования "formula" переименован в "as".

  • У ряда преобразований изменены имена выходных полей по умолчанию. Обычно это сделано для удобного использования результатов как свойств элементов графа сцены, например после визуального кодирования.

  • Преобразования размещения "pie", "stack" и "bin" больше не выводят рассчитанные середины интервалов, например layout_mid. Вычислите середину выражением "signal". После stack это можно сделать так: "y": {"scale": "yscale", "signal": "0.5 * (datum.y0 + datum.y1)"}.

  • Преобразование "aggregate" больше не использует блок "summarize". Начиная с Vega 3, поля, операции и имена выходных полей задаются отдельными массивами одинаковой длины:

    {
      "type": "aggregate",
      "groupby": ["category1", "category2"],
      "fields": ["measure1", "measure1", "measure2"],
      "ops": ["min", "max", "median"],
      "as": ["min1", "max1", "median2"]
    }
    
  • Для преобразования "bin":
    • Параметры "max" и "min" удалены. Вместо них используйте "extent" — массив [min, max], задающий диапазон интервалов.
    • Свойство "div" переименовано в "divide".
  • Параметр "test" преобразования "filter" переименован в "expr", как у других преобразований с выражениями.

  • У преобразования "lookup" параметры "on", "onKey" и "keys" переименованы соответственно в "from", "key" и "fields".

  • Преобразование "sort" удалено. В Vega 2 оно фактически лишь добавляло метку к проходящему потоку, а записи сортировались позднее, в конце цепочки преобразований. В Vega 3 сортировку задают одним из двух способов: (1) директивой "sort" в определении "domain" шкалы или (2) преобразованием "collect" с параметром "sort". Теперь сортировка выполняется в указанном месте потока данных. Если подходит первый способ, используйте его; иначе — второй.

  • Параметр "sortby" преобразования "stack" переименован в "sort".

К содержанию

Географические данные

  • Картографические проекции теперь определяются в собственном блоке верхнего уровня, подобно шкалам. Именованные проекции перечисляются в массиве свойства projections. Встроенные определения проекций внутри географических преобразований больше не допускаются; вместо них параметр "projection" указывает имя заранее определённой проекции.

  • Преобразование "geo" переименовано в "geopoint".

  • Для создания картографической градусной сетки добавлено преобразование "graticule". Создайте «пустой» набор данных без свойств "url" и "source", а преобразование "graticule" поставьте первым элементом массива "transform".

  • К "geopath" добавлено преобразование "geoshape", формирующее данные для нового примитива shape. Контур рассчитывается во время отрисовки. В Canvas это может заметно ускорить работу, поскольку географические данные не нужно преобразовывать в строку пути SVG.

К содержанию

Анимация

  • Начиная с Vega 3.0 анимированные переходы не поддерживаются. Поэтому свойства "delay" и "ease" больше не используются.

К содержанию

API представления

  • API представления Vega обновлён и упрощён. Чтобы создать визуализацию, сначала разберите спецификацию Vega, затем передайте полученное описание для среды выполнения конструктору View. В отличие от Vega 2.x, для этого не нужны асинхронные обработчики. Например:

    var runtime = vega.parse(spec); // при ошибке разбора может выбросить Error
    var view = new vega.View(runtime)
      .logLevel(vega.Warn) // задать уровень журналирования
      .initialize(document.querySelector('#view')) // задать родительский элемент DOM
      .renderer('svg') // выбрать рендерер (по умолчанию 'canvas')
      .hover() // включить обработку наведения
      .run(); // обновить и отрисовать представление
    
  • Вместо view.update метод view.run запускает проход потока данных и повторную отрисовку.

  • Вместо view.destroy для подготовки представления к удалению со страницы вызывайте view.finalize.

  • API View и система потока данных значительно переработаны. Экземпляр View теперь напрямую наследует Dataflow и управляет реактивными вычислениями, потоковым вводом данных и отрисовкой. Помимо справочника API представления, подробные комментарии JSDoc есть в исходном коде vega-view и vega-dataflow.

К содержанию