Использование vegaEmbed

Библиотека vega-embed служит связующим слоем между декларативными спецификациями визуализаций (Vega и Vega-Lite) и их отображением в DOM. Основная задача инструмента — упростить процесс рендеринга графиков, скрывая внутренние этапы компиляции, инициализации движка Vega и настройки взаимодействия.

В типичном сценарии vegaEmbed принимает контейнер и спецификацию визуализации, после чего выполняет полный цикл подготовки: преобразование Vega-Lite в Vega (если требуется), компиляцию, создание runtime-движка и отрисовку SVG или Canvas.


Сигнатура и базовая модель использования

Функция имеет следующий общий вид:

vegaEmbed(container, spec, options?)

Параметры:

  • container — DOM-элемент, селектор или ссылка на узел, в который будет встроена визуализация.
  • spec — объект спецификации Vega или Vega-Lite.
  • options — конфигурационный объект, управляющий рендерингом, поведением и инструментами взаимодействия.

Возвращаемое значение — Promise, который резолвится объектом:

{
  view: View,        // экземпляр Vega View
  spec: Object,      // финальная Vega-спецификация
  embedOptions: Object
}

Базовый процесс рендеринга

Минимальный пример использования:

import embed from 'vega-embed';

const spec = {
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": { "values": [10, 20, 30, 40] },
  "mark": "bar",
  "encoding": {
    "x": { "field": "data", "type": "quantitative" }
  }
};

embed('#vis', spec);

Процесс выполнения включает:

  1. Анализ типа спецификации (Vega или Vega-Lite)
  2. При необходимости — компиляция Vega-Lite → Vega
  3. Создание runtime-сцены
  4. Привязка к DOM-контейнеру
  5. Рендеринг (SVG или Canvas)

Работа с Vega-Lite спецификациями

Vega-Lite используется как высокоуровневое описание графиков. vegaEmbed автоматически трансформирует его в полноценную Vega-спецификацию.

Пример:

const spec = {
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "description": "Простой линейный график",
  "data": {
    "values": [
      { "x": 1, "y": 2 },
      { "x": 2, "y": 3 },
      { "x": 3, "y": 5 }
    ]
  },
  "mark": "line",
  "encoding": {
    "x": { "field": "x", "type": "quantitative" },
    "y": { "field": "y", "type": "quantitative" }
  }
};

embed('#vis', spec);

Внутренне выполняется компиляция через механизм Vega-Lite, после чего результат передаётся в Vega runtime.


Прямое использование Vega-спецификаций

При передаче нативной Vega-спецификации этап компиляции пропускается.

const spec = {
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "width": 400,
  "height": 200,
  "data": [
    {
      "name": "table",
      "values": [1, 2, 3, 4]
    }
  ],
  "marks": [
    {
      "type": "rect",
      "from": { "data": "table" },
      "encode": {
        "enter": {
          "x": { "scale": "xscale", "field": "data" }
        }
      }
    }
  ]
};

embed('#vis', spec);

Конфигурация options

Объект options управляет поведением рендера и инструментами взаимодействия.

Основные параметры

renderer

Определяет способ отрисовки:

  • "canvas" — высокая производительность при больших данных
  • "svg" — лучшая интерактивность и масштабирование
embed('#vis', spec, { renderer: 'canvas' });

actions

Управляет панелью действий (export, view source и т.д.):

embed('#vis', spec, {
  actions: false
});

или детальная настройка:

embed('#vis', spec, {
  actions: {
    export: true,
    source: false,
    compiled: false
  }
});

width и height

Позволяют переопределить размеры визуализации:

embed('#vis', spec, {
  width: 600,
  height: 300
});

theme

Поддержка встроенных тем оформления:

embed('#vis', spec, {
  theme: 'dark'
});

tooltip

Включение/настройка всплывающих подсказок:

embed('#vis', spec, {
  tooltip: true
});

Управление контейнером

container может задаваться тремя способами:

CSS-селектор

embed('#chart', spec);

DOM-элемент

const el = document.getElementById('chart');
embed(el, spec);

Создание внутри динамического узла

const div = document.createElement('div');
document.body.appendChild(div);

embed(div, spec);

При отсутствии контейнера создаётся ошибка выполнения, так как рендер невозможен без DOM-привязки.


Асинхронная модель и Promise

vegaEmbed возвращает Promise, что позволяет управлять процессом загрузки и инициализации:

embed('#vis', spec)
  .then(result => {
    const view = result.view;
  })
  .catch(error => {
    console.error(error);
  });

Экземпляр view предоставляет доступ к низкоуровневому API Vega Runtime.


Обновление визуализации

Перерисовка осуществляется либо повторным вызовом vegaEmbed, либо через методы view.

Пересоздание:

embed('#vis', newSpec);

Частичное обновление:

result.view
  .change('table', vega.changeset().insert(newData))
  .run();

Такой подход позволяет избегать полного пересоздания графика.


Обработка ошибок

Ошибки могут возникать на этапах:

  • парсинга спецификации
  • компиляции Vega-Lite
  • рендера сцены
  • привязки к DOM

Типичная обработка:

embed('#vis', spec)
  .catch(err => {
    console.error('Ошибка визуализации:', err);
  });

При отладке полезно включать режим отображения compiled spec через options.


Использование модулей и сборщиков

ESM (современный импорт)

import embed from 'vega-embed';

CommonJS

const embed = require('vega-embed');

CDN подключение

<script src="https://cdn.jsdelivr.net/npm/vega@5"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-lite@5"></script>
<script src="https://cdn.jsdelivr.net/npm/vega-embed@6"></script>

После подключения функция становится доступной как vegaEmbed.


Автоматическая компиляция Vega-Lite

Одной из ключевых особенностей является встроенный компилятор Vega-Lite. Он выполняет:

  • развертывание абстракций mark/encoding
  • генерацию scale, axis, legend
  • оптимизацию структуры сцены

В результате пользователь работает только с декларативным уровнем, не взаимодействуя с низкоуровневым Vega API напрямую.


События и интерактивность

Экземпляр view поддерживает систему событий:

view.addEventListener('click', function(event, item) {
  console.log(item);
});

Также поддерживаются:

  • hover-события
  • selection transforms
  • signal updates

Безопасность и sandbox-модель

Визуализации выполняются в рамках ограниченного runtime:

  • запрещён доступ к глобальному окружению
  • данные проходят через декларативные структуры
  • взаимодействие контролируется через signals и encodings

Это снижает риск выполнения произвольного кода при загрузке внешних спецификаций.


Типовые шаблоны интеграции

React-интеграция

import { useEffect, useRef } from 'react';
import embed from 'vega-embed';

function Chart({ spec }) {
  const ref = useRef(null);

  useEffect(() => {
    embed(ref.current, spec);
  }, [spec]);

  return <div ref={ref} />;
}

Vue-интеграция

mounted() {
  embed(this.$refs.chart, this.spec);
}

Производительность и оптимизация

Ключевые факторы влияния:

  • выбор canvas для больших датасетов
  • минимизация перерисовок
  • кэширование compiled spec
  • избежание повторного создания view

При высоконагруженных сценариях предпочтительно повторно использовать view, а не пересоздавать embed.


Частые архитектурные паттерны

Декларативное обновление

Изменение данных через реактивные потоки с пересборкой spec.

Императивное обновление

Использование view.change() для минимизации затрат на рендер.

Гибридный подход

Комбинация embed для инициализации и view API для обновлений данных.