Interact.js предоставляет мощный и гибкий инструмент для работы с перетаскиванием, изменением размера и жестами мультитача, опираясь на концепцию трансформаций и матриц. Понимание этих механизмов позволяет создавать сложные интерактивные интерфейсы, где элементы могут одновременно двигаться, вращаться и масштабироваться.
В основе трансформаций лежит матрица 2D-преобразований. Она описывает линейное преобразование точек на плоскости и позволяет объединять несколько операций в одну. Стандартная матрица 2D имеет вид:
[a, c, e]
[b, d, f]
[0, 0, 1]
Где:
a и d — масштабирование по осям X и Yb и c — наклон (skew)e и f — смещение (translate)Interact.js использует такие матрицы для отображения текущего состояния элемента, объединяя все примененные трансформации.
Interact.js позволяет управлять трансформациями через несколько ключевых событий и методов:
draggable — управление перемещением
элементов.resizable — изменение размеров с
учетом ограничений.gesturable — поддержка мультитач
жестов, включая вращение и масштабирование.Каждое из этих действий формирует объект interaction,
содержащий текущие значения трансформации,
например:
interaction.target.style.transform = `translate(${x}px, ${y}px) rotate(${angle}deg) scale(${scale})`;
Одновременное применение нескольких эффектов — перемещения,
масштабирования и вращения — требует аккуратного объединения
матриц. Interact.js автоматизирует этот процесс, предоставляя объект
interaction, в котором хранится текущая матрица
трансформации элемента. Пример:
interact('.draggable')
.draggable({
listeners: {
move(event) {
const target = event.target;
const x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
const y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.transform =
`translate(${x}px, ${y}px) ` +
`rotate(${parseFloat(target.getAttribute('data-rotate')) || 0}deg) ` +
`scale(${parseFloat(target.getAttribute('data-scale')) || 1})`;
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
}
});
В этом примере каждое перемещение аккумулируется, сохраняя текущее положение и одновременно сохраняя другие трансформации.
Для жестов мультитача используется модуль gesturable. Он
автоматически предоставляет параметры event.angle и
event.scale, которые можно интегрировать в текущую
трансформацию:
interact('.gesturable')
.gesturable({
listeners: {
move(event) {
const target = event.target;
const currentAngle = parseFloat(target.getAttribute('data-rotate')) || 0;
const currentScale = parseFloat(target.getAttribute('data-scale')) || 1;
const newAngle = currentAngle + event.da;
const newScale = currentScale * event.ds;
target.style.transform =
`rotate(${newAngle}deg) scale(${newScale}) ` +
`translate(${parseFloat(target.getAttribute('data-x')) || 0}px, ${parseFloat(target.getAttribute('data-y')) || 0}px)`;
target.setAttribute('data-rotate', newAngle);
target.setAttribute('data-scale', newScale);
}
}
});
Здесь event.da — изменение угла в градусах,
event.ds — коэффициент масштабирования. С помощью таких
данных можно динамически объединять трансляцию, вращение и
масштаб.
Interact.js предоставляет возможность использовать встроенные
функции для объединения матриц, чтобы создавать сложные
анимации и трансформации без ручного расчета. Например, библиотека
позволяет конвертировать текущие значения трансформации в
матрицу DOMMatrix, которая поддерживает методы
multiply, invert и translate:
const matrix = new DOMMatrix(window.getComputedStyle(target).transform);
matrix.translateSelf(dx, dy);
matrix.rotateSelf(dAngle);
matrix.scaleSelf(dScale);
target.style.transform = matrix.toString();
Преимущество такого подхода — возможность точно комбинировать любые преобразования, даже если они происходят одновременно, и легко управлять обратными преобразованиями.
Interact.js позволяет задавать ограничения трансформаций, чтобы контролировать движение и размер элементов:
restrict — ограничение по границам
контейнера.modifiers — дополнительные фильтры для
трансформаций (например, ограничение углов поворота или масштаба).Пример с ограничением перемещения внутри родительского блока:
interact('.draggable')
.draggable({
modifiers: [
interact.modifiers.restrictRect({
restriction: 'parent',
endOnly: true
})
]
});
Использование матриц особенно важно, когда необходимо:
Правильное управление матрицами позволяет избежать накопления ошибок и потери точности при последовательных трансформациях.