This commit is contained in:
Professional 2025-05-23 18:17:31 +07:00
parent 324f7d95df
commit 2c452f9f20

View File

@ -43,7 +43,7 @@
<div class="container"> <div class="container">
<div class="swipe-area" ref="swipeArea"> <div class="swipe-area" ref="swipeArea">
<!-- Swipeable Card Container --> <!-- Swipeable Card Container -->
<div class="card-stack-container" v-touch:swipe="handleSwipe"> <div class="card-stack-container">
<div <div
v-for="(user, index) in visibleUsers" v-for="(user, index) in visibleUsers"
:key="user._id" :key="user._id"
@ -55,10 +55,10 @@
'swiping-right': swipeDirection === 'right' && index === 0 'swiping-right': swipeDirection === 'right' && index === 0
}" }"
:style="index === 0 ? cardStyle : {}" :style="index === 0 ? cardStyle : {}"
v-touch:start="index === 0 ? startSwipe : null" @touchstart="index === 0 ? startTouch($event) : null"
v-touch:moving="index === 0 ? moveSwipe : null" @touchmove="index === 0 ? moveTouch($event) : null"
v-touch:end="index === 0 ? endSwipe : null" @touchend="index === 0 ? endTouch($event) : null"
@click="handleCardTap" @mousedown="index === 0 ? startDrag($event) : null"
> >
<!-- Photo Section --> <!-- Photo Section -->
<div class="card-photo-section"> <div class="card-photo-section">
@ -242,10 +242,18 @@ const swipeThreshold = 80; // Минимальное расстояние для
const cardStyle = ref({}); const cardStyle = ref({});
const swipeAngle = 12; // Угол наклона карты при свайпе (в градусах) const swipeAngle = 12; // Угол наклона карты при свайпе (в градусах)
const isPanning = ref(false); const isPanning = ref(false);
// Для touch событий
const touchStartX = ref(0); const touchStartX = ref(0);
const touchStartY = ref(0); const touchStartY = ref(0);
const touchCurrentX = ref(0); const touchEndX = ref(0);
const touchCurrentY = ref(0); const touchEndY = ref(0);
// Для mouse событий
const isDragging = ref(false);
const dragStartX = ref(0);
const dragStartY = ref(0);
const dragOffset = ref({ x: 0, y: 0 });
// Вычисляемые свойства // Вычисляемые свойства
const currentUserToSwipe = computed(() => { const currentUserToSwipe = computed(() => {
@ -306,21 +314,26 @@ const prevPhoto = (userId) => {
} }
}; };
// Обработчики жестов для vue3-touch-events // Обработчики touch событий
const startSwipe = (event) => { const startTouch = (event) => {
isPanning.value = true; isPanning.value = true;
touchStartX.value = event.touches[0].clientX; touchStartX.value = event.touches[0].clientX;
touchStartY.value = event.touches[0].clientY; touchStartY.value = event.touches[0].clientY;
// Сбросить конечные точки
touchEndX.value = 0;
touchEndY.value = 0;
}; };
const moveSwipe = (event) => { const moveTouch = (event) => {
if (!isPanning.value) return; if (!isPanning.value || !touchStartX.value) return;
const currentX = event.touches[0].clientX; const currentX = event.touches[0].clientX;
const currentY = event.touches[0].clientY; const currentY = event.touches[0].clientY;
touchCurrentX.value = currentX; // Сохраняем текущую позицию
touchCurrentY.value = currentY; touchEndX.value = currentX;
touchEndY.value = currentY;
const diffX = currentX - touchStartX.value; const diffX = currentX - touchStartX.value;
const diffY = currentY - touchStartY.value; const diffY = currentY - touchStartY.value;
@ -344,18 +357,16 @@ const moveSwipe = (event) => {
transition: 'none' transition: 'none'
}; };
// Предотвращаем скролл страницы при горизонтальном свайпе // Блокируем скролл страницы при горизонтальном свайпе
if (Math.abs(diffX) > Math.abs(diffY)) {
event.preventDefault(); event.preventDefault();
} }
}
}; };
const endSwipe = () => { const endTouch = (event) => {
if (!isPanning.value) return; if (!isPanning.value) return;
isPanning.value = false; isPanning.value = false;
const diffX = touchCurrentX.value - touchStartX.value; const diffX = touchEndX.value - touchStartX.value;
// Проверяем, достаточно ли было смещение для действия // Проверяем, достаточно ли было смещение для действия
if (Math.abs(diffX) > swipeThreshold) { if (Math.abs(diffX) > swipeThreshold) {
@ -389,19 +400,88 @@ const endSwipe = () => {
// Сбрасываем значения // Сбрасываем значения
touchStartX.value = 0; touchStartX.value = 0;
touchStartY.value = 0; touchStartY.value = 0;
touchCurrentX.value = 0; touchEndX.value = 0;
touchCurrentY.value = 0; touchEndY.value = 0;
}; };
const handleSwipe = (direction) => { // Обработчики mouse событий
// Эта функция будет вызываться при обнаружении свайпа v-touch:swipe const startDrag = (event) => {
// Можем использовать для дополнительной обработки isDragging.value = true;
console.log('Swipe detected:', direction); dragStartX.value = event.clientX;
dragStartY.value = event.clientY;
// Сброс смещения
dragOffset.value = { x: 0, y: 0 };
// Добавляем слушатели событий мыши на document
document.addEventListener('mousemove', moveDrag);
document.addEventListener('mouseup', endDrag);
}; };
const handleCardTap = (event) => { const moveDrag = (event) => {
// Обрабатываем обычный тап по карточке, если нужно if (!isDragging.value) return;
// Например, можно открыть полную информацию о пользователе
const currentX = event.clientX;
const currentY = event.clientY;
dragOffset.value = {
x: currentX - dragStartX.value,
y: currentY - dragStartY.value
};
// Определяем направление свайпа для индикаторов
if (Math.abs(dragOffset.value.x) > Math.abs(dragOffset.value.y)) {
if (dragOffset.value.x > 20) {
swipeDirection.value = 'right';
} else if (dragOffset.value.x < -20) {
swipeDirection.value = 'left';
} else {
swipeDirection.value = null;
}
// Применяем небольшой поворот для естественности
const rotate = dragOffset.value.x * 0.05;
// Точное следование за курсором
cardStyle.value = {
transform: `translateX(${dragOffset.value.x}px) rotate(${rotate}deg)`,
transition: 'none'
};
}
};
const endDrag = () => {
if (!isDragging.value) return;
// Проверяем, достаточно ли было смещение для действия
if (Math.abs(dragOffset.value.x) > swipeThreshold) {
// Если перетаскивание было достаточно большим, выполняем действие лайка/пропуска
if (dragOffset.value.x > 0) {
cardStyle.value = {
transform: `translateX(120%) rotate(${swipeAngle}deg)`,
transition: 'transform 0.3s ease'
};
setTimeout(() => handleLike(), 300);
} else {
cardStyle.value = {
transform: `translateX(-120%) rotate(-${swipeAngle}deg)`,
transition: 'transform 0.3s ease'
};
setTimeout(() => handlePass(), 300);
}
} else {
// Если перетаскивание небольшое, возвращаем карточку в исходное положение
cardStyle.value = {
transform: 'none',
transition: 'transform 0.3s ease'
};
swipeDirection.value = null;
}
// Сбрасываем состояние и удаляем слушатели
isDragging.value = false;
document.removeEventListener('mousemove', moveDrag);
document.removeEventListener('mouseup', endDrag);
}; };
// Основные функции // Основные функции
@ -569,7 +649,9 @@ onMounted(() => {
}); });
onUnmounted(() => { onUnmounted(() => {
// Здесь можно выполнить очистку, если необходимо // Удаляем обработчики мыши при размонтировании компонента
document.removeEventListener('mousemove', moveDrag);
document.removeEventListener('mouseup', endDrag);
}); });
// Следим за изменениями в списке предложений // Следим за изменениями в списке предложений