Адаптивность и изменение размеров

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

При инициализации экземпляра Two.js можно задать фиксированные размеры:

const elem = document.getElementById('draw-shapes');
const two = new Two({
  width: 800,
  height: 600,
}).appendTo(elem);

Если требуется адаптивность, размеры лучше задавать относительно контейнера:

const two = new Two({
  width: elem.clientWidth,
  height: elem.clientHeight,
}).appendTo(elem);

При изменении размеров контейнера необходимо обновлять сцену:

window.addEventListener('resize', () => {
  two.width = elem.clientWidth;
  two.height = elem.clientHeight;
  two.update(); // Перерисовка сцены
});

Использование renderer и соотношения сторон

Two.js поддерживает различные рендереры: SVG, Canvas и WebGL. Для адаптивности важно учитывать ratio, который влияет на плотность пикселей на экране (полезно для ретины):

const two = new Two({
  width: elem.clientWidth,
  height: elem.clientHeight,
  type: Two.Types.canvas,
  ratio: window.devicePixelRatio
}).appendTo(elem);

Использование ratio гарантирует, что объекты сцены будут оставаться чёткими на дисплеях с высокой плотностью пикселей.


Динамическое масштабирование объектов

Для сохранения пропорций объектов при изменении размеров экрана Two.js предлагает использовать группы и масштабирование:

const group = two.makeGroup();
const circle = two.makeCircle(100, 100, 50);
group.add(circle);

function resizeScene() {
  const scaleX = elem.clientWidth / 800;
  const scaleY = elem.clientHeight / 600;
  group.scale = Math.min(scaleX, scaleY); // сохраняем пропорции
  two.update();
}

window.addEventListener('resize', resizeScene);
resizeScene();

Использование групп позволяет централизованно управлять масштабом нескольких объектов одновременно, что упрощает создание адаптивных сцен.


Центрирование и привязка объектов

При адаптивном дизайне часто требуется, чтобы объекты оставались отцентрированными или привязанными к определённым областям контейнера. Two.js позволяет это делать через свойства translation:

circle.translation.set(elem.clientWidth / 2, elem.clientHeight / 2);

При каждом изменении размеров контейнера необходимо обновлять координаты объектов:

window.addEventListener('resize', () => {
  circle.translation.set(elem.clientWidth / 2, elem.clientHeight / 2);
  two.update();
});

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


Адаптивные линии, прямоугольники и кривые

При создании графики, зависящей от размеров окна, полезно задавать координаты относительно контейнера:

const line = two.makeLine(
  elem.clientWidth * 0.1, elem.clientHeight * 0.1,
  elem.clientWidth * 0.9, elem.clientHeight * 0.9
);

const rect = two.makeRectangle(
  elem.clientWidth / 2,
  elem.clientHeight / 2,
  elem.clientWidth * 0.5,
  elem.clientHeight * 0.3
);

Использование пропорциональных координат позволяет автоматически подстраивать размеры и положение элементов под любое разрешение экрана.


Автоматическое обновление сцен

Для полноценной адаптивности важно обновлять сцену не только при изменении размеров, но и при анимациях и интерактивных действиях. Two.js предоставляет метод two.update() для перерисовки сцены. В комбинации с requestAnimationFrame можно создать полностью динамическую адаптивную графику:

function animate() {
  requestAnimationFrame(animate);
  // Здесь можно изменять свойства объектов
  two.update();
}

animate();

Работа с элементами, привязанными к сетке

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

const gridWidth = elem.clientWidth / 10;
const gridHeight = elem.clientHeight / 10;

const square = two.makeRectangle(
  gridWidth * 2, gridHeight * 3,
  gridWidth, gridHeight
);

При изменении размеров контейнера сетка пересчитывается, а объекты остаются привязанными к своей позиции в сетке.


Итоговые рекомендации по адаптивности

  • Использовать elem.clientWidth и elem.clientHeight для задания размеров сцены.
  • Обновлять размеры сцены и объектов при событии resize.
  • Масштабировать группы объектов для сохранения пропорций.
  • Применять translation для центрирования и привязки объектов.
  • Использовать относительные координаты и размеры для линий, прямоугольников и кривых.
  • Комбинировать с requestAnimationFrame для плавных анимаций и интерактивности.

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