Interact.js — это мощная библиотека для управления интерактивными элементами в браузере. Одним из наиболее востребованных сценариев является создание изменяемых (resizable) панелей интерфейса, которые могут динамически изменять размер и перемещаться по странице. Библиотека предоставляет удобный API для обработки этих событий с высокой точностью и отзывчивостью.
Для того чтобы элемент стал изменяемым, необходимо подключить
Interact.js и применить метод interact() к
DOM-элементу:
interact('.panel')
.resizable({
edges: { left: true, right: true, bottom: true, top: true },
modifiers: [
interact.modifiers.restrictEdges({
outer: 'parent'
}),
interact.modifiers.restrictSize({
min: { width: 100, height: 100 },
max: { width: 800, height: 600 }
})
],
inertia: true
})
.on('resizemove', event => {
let target = event.target;
let x = (parseFloat(target.getAttribute('data-x')) || 0);
let y = (parseFloat(target.getAttribute('data-y')) || 0);
target.style.width = event.rect.width + 'px';
target.style.height = event.rect.height + 'px';
x += event.deltaRect.left;
y += event.deltaRect.top;
target.style.transform = `translate(${x}px, ${y}px)`;
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
});
Ключевые моменты:
edges — определяет стороны, за которые можно изменять
размер элемента. Можно разрешить или запретить растягивание по
конкретным направлениям.modifiers — набор ограничений.
restrictEdges предотвращает выход элемента за пределы
родителя, restrictSize задаёт минимальные и максимальные
размеры.inertia — добавляет эффект инерции, делая растягивание
более естественным.Interact.js позволяет объединять draggable и
resizable для одной панели, чтобы она могла перемещаться и
одновременно изменять размер:
interact('.panel')
.draggable({
listeners: {
move(event) {
let target = event.target;
let x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
let y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
target.style.transform = `translate(${x}px, ${y}px)`;
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
}
},
inertia: true
})
.resizable({
edges: { left: true, right: true, bottom: true, top: true },
modifiers: [
interact.modifiers.restrictEdges({
outer: 'parent'
}),
interact.modifiers.restrictSize({
min: { width: 100, height: 100 },
max: { width: 800, height: 600 }
})
],
inertia: true
});
Особенности комбинации:
transform: translate() сохраняет
позицию панели при изменении размеров.data-x и data-y позволяет
корректно отслеживать текущее положение панели без смещения при
повторных действиях.Чтобы панель не выходила за пределы родительского контейнера,
применяются модификаторы restrictEdges и
restrictSize. Важная деталь: необходимо учитывать, что
ограничение размера должно работать совместно с ограничением
перемещения, иначе панель может «вываливаться» за границы при быстром
изменении размеров.
modifiers: [
interact.modifiers.restrictEdges({
outer: 'parent',
endOnly: true
}),
interact.modifiers.restrictSize({
min: { width: 150, height: 150 },
max: { width: 600, height: 400 }
})
]
endOnly: true гарантирует, что ограничение будет
применяться только после завершения действия, что предотвращает дергание
панели во время растягивания.Interact.js предоставляет несколько событий, на которых можно выполнять дополнительные действия при изменении размера:
resizestart — начало изменения размеров. Можно
инициализировать визуальные эффекты или блокировать другие
элементы.resizemove — моментальное изменение размеров. Обычно
используется для обновления стилей и атрибутов.resizeend — завершение действия. Полезно для сохранения
состояния панели, отправки данных на сервер или обновления
интерфейса.Пример:
.on('resizestart', event => {
event.target.classList.add('resizing');
})
.on('resizeend', event => {
event.target.classList.remove('resizing');
console.log('Новые размеры:', event.rect.width, event.rect.height);
});
Для сложных интерфейсов часто требуется, чтобы изменяемые панели автоматически подстраивались под содержимое. Interact.js совместим с динамическими вычислениями размеров:
interact('.panel')
.resizable({
edges: { right: true, bottom: true },
modifiers: [
interact.modifiers.restrictSize({
min: { width: 200, height: 100 },
max: { width: 800, height: 600 }
})
]
})
.on('resizemove', event => {
let target = event.target;
target.style.width = event.rect.width + 'px';
target.style.height = event.rect.height + 'px';
// Автоподстройка содержимого
const content = target.querySelector('.content');
if (content) {
content.style.height = (event.rect.height - 20) + 'px';
}
});
.content обеспечивает
гибкую компоновку и предотвращает переполнение текста или других
элементов.flex или grid, чтобы
панели масштабировались вместе с контентом.Для удобства пользователей необходимо визуально обозначать области для растягивания. Обычно применяют псевдоэлементы или специальные «ручки»:
.panel {
position: absolute;
border: 2px solid #333;
box-sizing: border-box;
}
.panel::after {
content: '';
position: absolute;
width: 12px;
height: 12px;
right: 0;
bottom: 0;
cursor: se-resize;
background: #666;
}
cursor: se-resize информирует о направлении изменения
размера.transform: translate вместо
изменения top/left для плавного перемещения и
оптимизации производительности.resizestart,
resizemove, resizeend) для синхронизации
данных и визуальных эффектов.