Сенсорные события в браузере позволяют отслеживать взаимодействие
пользователя с устройствами ввода, такими как сенсорные экраны. В Vue.js
обработка таких событий осуществляется через директиву
v-on, которая связывает события DOM с методами
компонента.
Основные события сенсорного ввода:
touchstart — возникает при начале касания экрана.touchmove — возникает при перемещении пальца по
экрану.touchend — возникает при окончании касания.touchcancel — возникает при отмене касания системой
(например, при появлении уведомления).Пример базового использования:
<template>
<div
class="touch-area"
@touchstart="onTouchStart"
@touchmove="onTouchMove"
@touchend="onTouchEnd"
>
Сенсорная область
</div>
</template>
<script>
export default {
methods: {
onTouchStart(event) {
console.log('Касание началось', event.touches[0].clientX, event.touches[0].clientY);
},
onTouchMove(event) {
console.log('Касание движется', event.touches[0].clientX, event.touches[0].clientY);
},
onTouchEnd(event) {
console.log('Касание завершено');
}
}
}
</script>
<style scoped>
.touch-area {
width: 300px;
height: 200px;
background-color: #f0f0f0;
border: 1px solid #ccc;
display: flex;
align-items: center;
justify-content: center;
user-select: none;
}
</style>
Ключевой момент: объект события event содержит массив
touches — список всех активных касаний. Для определения
конкретного касания используется индекс [0], если требуется
работать с первым касанием.
Жесты — это комбинации сенсорных событий, интерпретируемых как определённые действия: свайпы, пинч-зум, вращение. Vue.js не предоставляет встроенной системы распознавания жестов, но её можно реализовать через вычисление изменения координат касаний.
Пример реализации свайпа:
<template>
<div
class="swipe-area"
@touchstart="startSwipe"
@touchend="endSwipe"
>
Проведите пальцем
</div>
</template>
<script>
export default {
data() {
return {
startX: 0,
startY: 0,
}
},
methods: {
startSwipe(event) {
this.startX = event.touches[0].clientX;
this.startY = event.touches[0].clientY;
},
endSwipe(event) {
const endX = event.changedTouches[0].clientX;
const endY = event.changedTouches[0].clientY;
const deltaX = endX - this.startX;
const deltaY = endY - this.startY;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
if (deltaX > 50) {
console.log('Свайп вправо');
} else if (deltaX < -50) {
console.log('Свайп влево');
}
} else {
if (deltaY > 50) {
console.log('Свайп вниз');
} else if (deltaY < -50) {
console.log('Свайп вверх');
}
}
}
}
}
</script>
<style scoped>
.swipe-area {
width: 300px;
height: 200px;
background-color: #e0e0ff;
border: 1px solid #999;
display: flex;
align-items: center;
justify-content: center;
user-select: none;
}
</style>
Особенности обработки:
event.changedTouches содержит список касаний,
завершившихся на данном элементе.deltaX,
deltaY) для определения направления свайпа.Для обработки пинч-зума необходимо использовать два касания одновременно и вычислять расстояние между ними. Изменение этого расстояния позволяет определить увеличение или уменьшение масштаба.
Пример вычисления масштаба:
calculateDistance(touch1, touch2) {
const dx = touch2.clientX - touch1.clientX;
const dy = touch2.clientY - touch1.clientY;
return Math.sqrt(dx * dx + dy * dy);
}
При изменении touchmove расстояние сравнивается с
исходным, чтобы определить направление жеста:
Vue позволяет создавать собственные директивы для работы с сенсорными событиями. Это удобно, если одни и те же жесты применяются к разным компонентам.
Пример директивы для свайпа:
app.directive('swipe', {
beforeMount(el, binding) {
let startX, startY;
el.addEventListener('touchstart', (e) => {
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
});
el.addEventListener('touchend', (e) => {
const endX = e.changedTouches[0].clientX;
const endY = e.changedTouches[0].clientY;
const deltaX = endX - startX;
const deltaY = endY - startY;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
if (deltaX > 50) binding.value('right');
else if (deltaX < -50) binding.value('left');
} else {
if (deltaY > 50) binding.value('down');
else if (deltaY < -50) binding.value('up');
}
});
}
});
Использование:
<div v-swipe="onSwipe">Проведите пальцем</div>
<script>
export default {
methods: {
onSwipe(direction) {
console.log('Свайп:', direction);
}
}
}
</script>
Директива упрощает повторное использование логики жестов, делая код более чистым и модульным.
Сенсорные события часто применяются для управления анимациями,
например, свайп для закрытия карточки. Vue Transition API позволяет
плавно менять состояние элемента при жестах, комбинируя события с
v-if или v-show.
Пример использования с переходами:
<template>
<transition name="slide">
<div v-if="visible" v-swipe="handleSwipe" class="card">
Карточка
</div>
</transition>
</template>
<script>
export default {
data() {
return { visible: true };
},
methods: {
handleSwipe(direction) {
if (direction === 'left') this.visible = false;
}
}
}
</script>
<style>
.slide-enter-active, .slide-leave-active {
transition: transform 0.3s ease;
}
.slide-enter-from, .slide-leave-to {
transform: translateX(100%);
}
</style>
touchmove и других
событий, чтобы избежать блокировки скролла:el.addEventListener('touchmove', handler, { passive: true });
touchmove, например, с помощью
requestAnimationFrame.Сенсорные события и жесты во Vue.js позволяют создавать интерактивные мобильные интерфейсы, полностью управляемые через реактивные данные и методы компонентов. Директивы, вычисления координат и оптимизация производительности — ключевые инструменты для эффективной работы с сенсорными взаимодействиями.