Обрезка изображений

Библиотека Two.js ориентирована на работу с векторной графикой, однако поддерживает и растровые изображения через объект Two.Texture. Обрезка изображений напрямую в API не представлена как отдельный высокоуровневый метод, но реализуется за счёт управления текстурой, координатами отображения и масками.

Основная идея: отображается не всё изображение, а только его часть, задаваемая либо через свойства текстуры, либо через геометрические ограничения (маскирование).


Объект Texture и его параметры

Изображения подключаются через объект Two.Texture:

const texture = new Two.Texture('image.jpg');

Ключевые свойства:

  • image — сам источник изображения
  • loaded — флаг загрузки
  • repeat — режим повторения
  • offset — смещение текстуры
  • scale — масштаб текстуры

Для обрезки особенно важны:

  • offset
  • scale

Обрезка через смещение и масштаб

Один из базовых способов — изменение области отображения за счёт комбинации offset и scale.

Принцип

  • scale увеличивает или уменьшает изображение
  • offset смещает видимую часть

Пример

const texture = new Two.Texture('image.jpg');

const rect = two.makeRectangle(200, 200, 300, 200);
rect.fill = texture;

// Увеличиваем изображение
texture.scale = new Two.Vector(2, 2);

// Смещаем "окно просмотра"
texture.offset = new Two.Vector(-100, -50);

Интерпретация

  • Масштаб увеличивает изображение в 2 раза
  • Смещение «сдвигает» изображение внутри фигуры
  • В результате видна только часть картинки

Использование геометрии как области обрезки

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

форма фигуры = область видимости изображения

Прямоугольная обрезка

const texture = new Two.Texture('image.jpg');

const rect = two.makeRectangle(250, 250, 200, 150);
rect.fill = texture;

Изображение будет автоматически “обрезано” границами прямоугольника.


Обрезка произвольной формы

Возможность использовать любую форму — одно из преимуществ Two.js.

Пример: круг

const texture = new Two.Texture('image.jpg');

const circle = two.makeCircle(250, 250, 100);
circle.fill = texture;

Изображение будет отображаться только внутри круга.


Маскирование (Masking)

Для более гибкой обрезки используется механизм масок.

Принцип

  • создаётся маска (любая фигура)
  • маска назначается объекту через свойство mask
  • отображается только пересечение

Пример

const texture = new Two.Texture('image.jpg');

const rect = two.makeRectangle(250, 250, 300, 200);
rect.fill = texture;

const mask = two.makeCircle(250, 250, 100);

rect.mask = mask;

Особенности

  • маска может быть любой сложности
  • можно анимировать маску
  • маска не отображается сама по себе

Динамическая обрезка

Two.js позволяет изменять параметры в реальном времени.

Пример анимации обрезки

two.bind('update', function(frameCount) {
  texture.offset.x = Math.sin(frameCount * 0.05) * 100;
});

В результате:

  • изображение «движется» внутри области
  • создаётся эффект скроллинга или панорамирования

Работа с координатами текстуры

Координатная система текстуры отличается от координат сцены.

Важные моменты:

  • центр текстуры совпадает с центром фигуры
  • offset задаётся относительно центра
  • положительные значения двигают текстуру вправо и вниз

Управление масштабом и пропорциями

При обрезке важно учитывать соотношение сторон:

texture.scale = new Two.Vector(1.5, 1);

Это приведёт к:

  • растяжению изображения по горизонтали
  • искажению пропорций

Для сохранения пропорций:

texture.scale = new Two.Vector(1.5, 1.5);

Кадрирование (Crop-подобный эффект)

Для имитации классического crop:

  1. задаётся фиксированная область (фигура)
  2. изменяется offset
  3. подбирается scale

Пример

const texture = new Two.Texture('image.jpg');

const frame = two.makeRectangle(250, 250, 200, 200);
frame.fill = texture;

// Масштабируем изображение под рамку
texture.scale = new Two.Vector(1.2, 1.2);

// Центрируем нужную область
texture.offset = new Two.Vector(-50, 30);

Обрезка спрайтов (Sprite Sheet)

Two.js не имеет встроенной системы спрайтов, но обрезку можно использовать для отображения кадров.

Принцип

  • одна текстура содержит множество кадров
  • через offset показывается нужный участок

Пример

const texture = new Two.Texture('sprites.png');

const sprite = two.makeRectangle(100, 100, 64, 64);
sprite.fill = texture;

let frame = 0;

two.bind('update', function() {
  const frameWidth = 64;
  texture.offset.x = -frame * frameWidth;
  frame = (frame + 1) % 10;
});

Ограничения и особенности

  • нет прямого API crop(x, y, width, height)

  • обрезка реализуется косвенно через:

    • геометрию
    • маски
    • смещение текстуры
  • поведение может отличаться в зависимости от рендерера (SVG / Canvas / WebGL)


Оптимизация

При работе с обрезкой важно учитывать производительность:

  • избегать частого изменения Texture, если это возможно
  • использовать WebGL-рендерер для сложных сцен
  • минимизировать количество масок

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

Аватары

  • круглая маска
  • центрирование лица через offset

Галереи

  • обрезка изображений под одинаковые размеры

Игры

  • отображение части карты
  • работа со спрайтами

UI-элементы

  • прогресс-бары с маской
  • анимированные превью

Комбинирование техник

Наиболее гибкий результат достигается при объединении подходов:

  • форма + offset
  • форма + масштаб
  • маска + анимация
  • спрайт + маска

Пример комплексного использования:

const texture = new Two.Texture('image.jpg');

const rect = two.makeRectangle(250, 250, 200, 200);
rect.fill = texture;

const mask = two.makeRoundedRectangle(250, 250, 180, 180, 20);

rect.mask = mask;

texture.scale = new Two.Vector(1.3, 1.3);
texture.offset = new Two.Vector(-30, 10);

Визуальный контроль обрезки

Для точной настройки полезно временно:

  • отключать маску
  • добавлять рамку (stroke)
  • отображать вспомогательные фигуры
rect.stroke = 'red';
rect.linewidth = 2;

Работа с загрузкой изображений

Важно учитывать асинхронную загрузку:

texture.bind('load', function() {
  // безопасная настройка обрезки
});

Без этого возможны:

  • некорректные размеры
  • неправильное позиционирование

Расширенные техники

Использование нескольких масок

Two.js напрямую поддерживает одну маску, но можно:

  • вложить объекты в группы
  • применять маску к группе
const group = two.makeGroup(rect);
group.mask = mask;

Псевдо-обрезка через clipPath (SVG)

В SVG-рендерере возможно использование clipPath, который Two.js генерирует автоматически при маскировании.


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

Рендерер Особенности
Canvas быстрее, но меньше контроля
SVG точное маскирование
WebGL высокая производительность

Частые ошибки

  • неправильный offset (перепутаны оси)
  • несоответствие масштаба и размера фигуры
  • отсутствие ожидания загрузки изображения
  • искажение пропорций

Структура типичного решения

  1. загрузка изображения
  2. создание фигуры (области)
  3. применение текстуры
  4. настройка масштаба
  5. настройка смещения
  6. при необходимости — маска
  7. анимация или взаимодействие

Итоговая концепция

Обрезка в Two.js — это не отдельная операция, а комбинация:

  • геометрии
  • текстурных координат
  • масок

Такой подход даёт гибкость и позволяет реализовать практически любой сценарий отображения изображений в рамках 2D-графики.