Минимизация перерисовок

Two.js — библиотека для работы с 2D-графикой на веб-странице, которая использует Canvas, SVG и WebGL как рендереры. Эффективная работа с визуальными объектами напрямую зависит от управления перерисовками, так как каждая перерисовка требует вычислений и обращения к графическому контексту, что влияет на производительность, особенно при анимации большого числа объектов.

Использование upd ate() и render()

В Two.js существует явное разделение логики изменения сцены и рендеринга:

  • Метод upd ate() используется для изменения состояния объектов (позиция, масштаб, цвет, трансформации).
  • Метод render() отвечает за непосредственную отрисовку текущего состояния на экране.

Перерисовки следует минимизировать за счет накопления всех изменений и вызова render() один раз за кадр:

two.update();
two.render();

Повторные вызовы render() без необходимости создают лишнюю нагрузку. Для анимации рекомендуется использовать встроенный метод two.bind('update', ...) или two.play() с заранее подготовленными анимациями.

Группировка объектов и контейнеров

Two.js поддерживает иерархию объектов с помощью Group. Все элементы внутри группы можно изменять и рендерить как единое целое. Это уменьшает количество перерисовок отдельных объектов:

let group = two.makeGroup(circle, rectangle, polygon);
group.translation.se t(100, 50);
two.update();

При перемещении группы обновляется только контейнер, а дочерние элементы рендерятся вместе, без отдельного обращения к каждому.

Использование flagReset() и flagSet()

Каждый объект Two.js содержит флаги изменений:

  • needsUpdate — объект изменился, требует перерисовки.
  • needsLocalUpdate — локальные свойства трансформации изменились.

После внесения изменений в объект желательно использовать метод flagReset() для сброса флагов, чтобы избежать ненужных повторных обновлений:

circle.fill = '#ff0000';
circle.flagReset();
two.update();

Анимация и оптимизация кадра

Two.js работает на основе цикла анимации, используя requestAnimationFrame. Минимизировать перерисовки при анимации можно путем:

  1. Изменения только тех свойств, которые действительно изменяются.
  2. Группировки объектов и анимации группы вместо отдельных элементов.
  3. Использования Two.Shape и Two.Path вместо создания новых объектов каждый кадр.

Пример оптимизированной анимации:

two.bind('upd ate', function(frameCount) {
  circle.rotation += 0.01; // изменяем только угол
}).play();

Кэширование геометрии

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

let staticPath = two.makePolygon(0, 0, 50, 6);
staticPath.noStroke().fill = '#333';
staticPath.flagReset(); // больше не требует перерисовки

Избегание лишних свойств при изменениях

Каждое изменение свойства объекта (цвет, прозрачность, позиция) помечает объект как dirty. Избыточные изменения увеличивают число перерисовок. Поэтому:

  • Обновлять только изменяемые свойства.
  • Использовать методы translation.se t(x, y) вместо прямой установки translation.x и translation.y по отдельности.
// Плохо
circle.translation.x = 100;
circle.translation.y = 50;

// Хорошо
circle.translation.se t(100, 50);

Итоговая схема оптимизации перерисовок

  1. Создать объекты один раз и повторно использовать их.
  2. Группировать объекты для совместного рендеринга.
  3. Изменять только нужные свойства.
  4. Использовать методы update(), render() и флаги flagReset() для контроля перерисовок.
  5. Кэшировать сложные статические объекты и формы.
  6. При анимации работать с кадром через bind('update', ...) и изменять минимальный набор свойств.

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