Переключение между рендерерами

Two.js поддерживает несколько рендереров: SVG, Canvas и WebGL. Каждый из них имеет свои особенности и ограничения, и возможность переключения между ними в процессе работы позволяет оптимизировать производительность и визуальное качество сцены.

Инициализация Two.js с разными рендерерами

Для создания экземпляра Two.js используется объект конфигурации с ключом type.

const paramsSVG = { width: 800, height: 600, type: Two.Types.svg };
const twoSVG = new Two(paramsSVG).appendTo(document.body);

const paramsCanvas = { width: 800, height: 600, type: Two.Types.canvas };
const twoCanvas = new Two(paramsCanvas).appendTo(document.body);

const paramsWebGL = { width: 800, height: 600, type: Two.Types.webgl };
const twoWebGL = new Two(paramsWebGL).appendTo(document.body);

Ключевые моменты:

  • Two.Types.svg создает векторный рендер через SVG.
  • Two.Types.canvas использует стандартный HTML <canvas>.
  • Two.Types.webgl обеспечивает аппаратное ускорение и работу с шейдерами.

Создание элементов, независимых от рендерера

Two.js предоставляет унифицированный API для создания примитивов: линии, фигуры, группы. Это означает, что одна и та же сцена может быть повторно использована с разными рендерерами.

const circle = twoSVG.makeCircle(400, 300, 50);
circle.fill = '#FF8000';
circle.stroke = '#000';
circle.linewidth = 5;

После создания объектов их можно добавить в другую сцену, даже с другим рендерером:

twoCanvas.add(circle);
twoWebGL.add(circle);

Важно понимать: при переключении рендереров фактически создается новый экземпляр Two, поэтому старые элементы нужно повторно добавлять или клонировать.

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

Two.js не поддерживает динамическое изменение типа рендерера у существующего экземпляра. Для переключения требуется:

  1. Сохранить все объекты сцены.
  2. Уничтожить текущий экземпляр (two.clear() и удаление DOM-контейнера).
  3. Создать новый Two с желаемым типом рендерера.
  4. Добавить объекты обратно в новую сцену.

Пример:

function switchRenderer(currentTwo, newType) {
    const elements = currentTwo.scene.children.slice(); // копия всех элементов
    currentTwo.clear();
    currentTwo.renderer.domElement.remove(); // удаление старого DOM
    const newTwo = new Two({ width: 800, height: 600, type: newType }).appendTo(document.body);
    elements.forEach(el => newTwo.add(el));
    newTwo.update();
    return newTwo;
}

// Использование:
twoSVG = switchRenderer(twoSVG, Two.Types.webgl);

Ограничения при смене рендерера

  • SVG не поддерживает некоторые WebGL-эффекты, например градиентные шейдеры и прозрачные текстуры с WebGL.
  • Canvas не масштабируется без потери качества как SVG.
  • WebGL требует GPU и поддерживает больше визуальных эффектов, но может быть избыточен для простых 2D-сцен.

Оптимизация переключения

  • Хранение структуры сцены отдельно от рендерера облегчает повторное создание сцены.
  • Использование групп (Two.Group) позволяет переносить сразу несколько объектов.
  • Минимизировать количество операций с DOM при удалении и добавлении новых рендереров.
const group = twoSVG.makeGroup(circle, twoSVG.makeRectangle(200, 200, 100, 50));
twoCanvas.add(group.clone()); // быстрый перенос всей группы

Обновление сцены после смены рендерера

После добавления объектов в новый экземпляр Two необходимо вызвать two.update() для рендеринга текущего состояния сцены. Если используется анимация, также требуется повторно запустить рендер-цикл:

two.bind('update', function(frameCount) {
    circle.rotation += 0.01;
}).play();

Рекомендации по выбору рендерера

  • Для статичной графики и сложной векторной визуализации — SVG.
  • Для быстрой анимации с простыми фигурами — Canvas.
  • Для эффектных визуализаций с прозрачностью, текстурами и шейдерами — WebGL.

Эффективное переключение между рендерерами позволяет комбинировать преимущества каждого подхода, сохраняя гибкость работы с Two.js и производительность в различных браузерах и устройствах.