Библиотека Interact.js предоставляет удобный способ реализации интерактивных действий с элементами DOM, включая перетаскивание, масштабирование и вращение. Вращение элементов позволяет пользователям изменять ориентацию объекта на странице с помощью мыши или сенсорного ввода, создавая динамичный и интерактивный интерфейс.
В Interact.js вращение реализуется через масштабирование с
модификацией угла или через расширение стандартного
draggable и gesturable API. Основные методы
вращения опираются на события gesturemove или кастомные
обработчики углов.
Для начала необходимо подключить библиотеку:
<script src="https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js"></script>
И выбрать элемент, который будет вращаться:
const rotateElement = document.querySelector('.rotatable');
gesturable для вращенияInteract.js предоставляет метод gesturable(), который
отслеживает жесты масштабирования и вращения на сенсорных
устройствах. Пример базовой настройки вращения:
interact(rotateElement)
.gesturable({
onstart: function (event) {
// Инициализация начального угла
event.target.dataset.angle = event.target.dataset.angle || 0;
},
onmove: function (event) {
let currentAngle = parseFloat(event.target.dataset.angle) || 0;
currentAngle += event.da; // da — изменение угла в градусах
event.target.style.transform = `rotate(${currentAngle}deg)`;
event.target.dataset.angle = currentAngle;
},
onend: function (event) {
// Можно сохранять финальный угол или выполнять другие действия
}
});
Ключевые моменты:
event.da — изменение угла за текущий шаг события, в
градусах.dataset.angle используется для хранения текущего угла
между событиями, чтобы не терять позицию.transform: rotate(...) применяется непосредственно к
CSS элемента.Для создания комплексного интерактивного элемента часто требуется
совместить draggable, resizable и
gesturable. Это позволяет пользователю не только вращать
объект, но и перемещать и изменять его размеры.
interact(rotateElement)
.draggable({
listeners: {
move(event) {
const target = event.target;
const x = (parseFloat(target.dataset.x) || 0) + event.dx;
const y = (parseFloat(target.dataset.y) || 0) + event.dy;
target.style.transform = `translate(${x}px, ${y}px) rotate(${target.dataset.angle || 0}deg)`;
target.dataset.x = x;
target.dataset.y = y;
}
}
})
.gesturable({
onmove(event) {
let angle = parseFloat(event.target.dataset.angle) || 0;
angle += event.da;
const x = parseFloat(event.target.dataset.x) || 0;
const y = parseFloat(event.target.dataset.y) || 0;
event.target.style.transform = `translate(${x}px, ${y}px) rotate(${angle}deg)`;
event.target.dataset.angle = angle;
}
});
Особенности совместного использования:
transform
для предотвращения конфликтов CSS.dataset.x,
dataset.y) и угол (dataset.angle), чтобы
корректно комбинировать действия.resizable с учетом
текущей ориентации.Interact.js позволяет устанавливать ограничения на угол вращения, чтобы элемент не превышал заданный диапазон:
interact(rotateElement)
.gesturable({
onmove(event) {
let angle = parseFloat(event.target.dataset.angle) || 0;
angle += event.da;
// Ограничение от -45 до 45 градусов
angle = Math.max(-45, Math.min(45, angle));
const x = parseFloat(event.target.dataset.x) || 0;
const y = parseFloat(event.target.dataset.y) || 0;
event.target.style.transform = `translate(${x}px, ${y}px) rotate(${angle}deg)`;
event.target.dataset.angle = angle;
}
});
Преимущества ограничения:
Для устройств без сенсорного экрана вращение можно реализовать через
mousedown + mousemove события с вычислением
угла между курсором и центром элемента:
rotateElement.addEventListener('mousedown', startRotate);
function startRotate(event) {
const rect = rotateElement.getBoundingClientRect();
const centerX = rect.left + rect.width / 2;
const centerY = rect.top + rect.height / 2;
function onMouseMove(moveEvent) {
const dx = moveEvent.clientX - centerX;
const dy = moveEvent.clientY - centerY;
let angle = Math.atan2(dy, dx) * (180 / Math.PI); // угол в градусах
rotateElement.style.transform = `rotate(${angle}deg)`;
rotateElement.dataset.angle = angle;
}
function stopRotate() {
window.removeEventListener('mousemove', onMouseMove);
window.removeEventListener('mouseup', stopRotate);
}
window.addEventListener('mousemove', onMouseMove);
window.addEventListener('mouseup', stopRotate);
}
Особенности этого подхода:
atan2 обеспечивает корректное
вращение во всех квадрантах.draggable для комплексного
взаимодействия.dataset для хранения текущих
параметров трансформации. Это предотвращает потерю состояния при
перерисовке страницы или пересоздании событий.transform, чтобы
избежать конфликтов CSS.gesturable(), так как он автоматически учитывает мультитач
и масштабирование.В результате, использование Interact.js для вращения элементов обеспечивает гибкий, кроссплатформенный подход, позволяющий создавать интерактивные интерфейсы с контролем положения, ориентации и комбинированного взаимодействия объектов.