feat(CP页面): 处理触摸事件滑动和点击事件冲突的问题
This commit is contained in:
parent
06bff5843e
commit
e8cd6bed98
@ -63,6 +63,7 @@
|
||||
@touchstart="handleTouchStart"
|
||||
@touchmove="handleTouchMove"
|
||||
@touchend="handleTouchEnd"
|
||||
style="touch-action: pan-x"
|
||||
>
|
||||
<!-- 右占位 -->
|
||||
<div style="width: 9vw; min-width: 0; flex-shrink: 0"></div>
|
||||
@ -70,38 +71,44 @@
|
||||
<!-- top1情侣头像 -->
|
||||
<itemCenter
|
||||
v-for="(item, index) in seasonTop1List"
|
||||
:key="`couple-${item.userId || index}`"
|
||||
style="z-index: 1; min-width: 0; flex-shrink: 0; transition: all 0.8s ease"
|
||||
:style="{ width: index === centerIndex ? '60vw' : '40vw' }"
|
||||
:style="{
|
||||
width: index === centerIndex ? '60vw' : '40vw',
|
||||
zIndex: index === centerIndex ? 20 : 1,
|
||||
}"
|
||||
:imgUrl="twelveSigns[index]?.bgUrl"
|
||||
:contentStyle="``"
|
||||
>
|
||||
<!-- 非居中时显示遮罩层用于移动 -->
|
||||
<div
|
||||
v-if="index !== centerIndex"
|
||||
style="position: absolute; z-index: 10; inset: 0"
|
||||
style="position: absolute; inset: 0; z-index: 9; pointer-events: auto"
|
||||
@click.stop="moveToCenter(index)"
|
||||
></div>
|
||||
|
||||
<!-- 点击事件 -->
|
||||
<div
|
||||
v-if="index === centerIndex"
|
||||
style="
|
||||
position: absolute;
|
||||
z-index: 9;
|
||||
inset: 0;
|
||||
z-index: 20;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
pointer-events: none;
|
||||
"
|
||||
>
|
||||
<!-- 情侣1 -->
|
||||
<div
|
||||
style="flex: 1; min-width: 0; align-self: stretch"
|
||||
@click="viewUserInfo(item.userId)"
|
||||
style="flex: 1; min-width: 0; align-self: stretch; pointer-events: auto"
|
||||
@click.stop="handleAvatarClick(item.userId)"
|
||||
></div>
|
||||
<!-- 情侣2 -->
|
||||
<div
|
||||
style="flex: 1; min-width: 0; align-self: stretch"
|
||||
@click="viewUserInfo(item.cpUserId)"
|
||||
style="flex: 1; min-width: 0; align-self: stretch; pointer-events: auto"
|
||||
@click.stop="handleAvatarClick(item.cpUserId)"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
@ -1448,9 +1455,14 @@ const resultShowIndex = ref(0) // 抽奖结果索引
|
||||
const seasonTop1List = ref([]) // 赛季榜Top1列表
|
||||
const listLeftPosition = ref('0') //top历史榜单
|
||||
const centerIndex = ref(0) // 默认中间项的索引为1
|
||||
|
||||
// 添加触摸滑动相关变量
|
||||
const touchStartX = ref(0)
|
||||
const touchEndX = ref(0)
|
||||
const isSwipe = ref(false) // ✅ 新增:标记是否为滑动
|
||||
const isMoving = ref(false)
|
||||
const lastClickTime = ref(0) // ✅ 新增:记录上次点击时间
|
||||
const clickLock = ref(false) // ✅ 新增:点击锁,防止同一事件多次触发
|
||||
|
||||
const twelveSigns = ref([
|
||||
{ name: 'Aquarius', time: '2026.1.20-2.18', bgUrl: imageUrl('AquariusCoupleFrame') }, // 水瓶座
|
||||
@ -1467,54 +1479,141 @@ const twelveSigns = ref([
|
||||
{ name: 'Capricorn', time: '2026.12.22-1.19', bgUrl: imageUrl('') }, // 摩羯座
|
||||
]) // 十二星座
|
||||
|
||||
// 计算移动到中心位置的函数
|
||||
const moveToCenter = (targetIndex) => {
|
||||
if (centerIndex.value == targetIndex) return // 如果当前索引和目标索引相同,则不需要移动
|
||||
// 点击居中项头像
|
||||
const handleAvatarClick = (userId, event) => {
|
||||
const now = Date.now()
|
||||
|
||||
centerIndex.value = targetIndex
|
||||
updatePosition() // 更新位置
|
||||
}
|
||||
|
||||
// 触发触摸开始事件
|
||||
const handleTouchStart = (event) => {
|
||||
touchStartX.value = event.touches[0].clientX
|
||||
}
|
||||
|
||||
// 触发触摸移动事件
|
||||
const handleTouchMove = (event) => {
|
||||
touchEndX.value = event.touches[0].clientX
|
||||
}
|
||||
|
||||
// 触发触摸结束事件
|
||||
const handleTouchEnd = () => {
|
||||
if (!touchStartX.value) return
|
||||
|
||||
let minSwipeDistance = 50 //x轴最小滑动距离
|
||||
let distance = touchEndX.value - touchStartX.value // 左滑<0 右滑>0
|
||||
let isLeftSwipe = distance < -minSwipeDistance // 满足左滑
|
||||
let isRightSwipe = distance > minSwipeDistance // 满足右滑
|
||||
|
||||
if (isLeftSwipe) {
|
||||
// 左滑
|
||||
if (centerIndex.value > 0) {
|
||||
moveToCenter(centerIndex.value - 1)
|
||||
}
|
||||
} else if (isRightSwipe) {
|
||||
// 右滑
|
||||
if (centerIndex.value < seasonTop1List.value.length - 1) {
|
||||
moveToCenter(centerIndex.value + 1)
|
||||
}
|
||||
// 滑动中不触发点击(防止滑动时误触)
|
||||
if (isSwipe.value) {
|
||||
event?.stopPropagation() // 滑动中阻止点击
|
||||
return
|
||||
}
|
||||
|
||||
// 重置触摸变量
|
||||
// 移动动画中不触发点击
|
||||
if (isMoving.value) {
|
||||
event?.stopPropagation()
|
||||
return
|
||||
}
|
||||
|
||||
// 点击锁检查(防止重复触发)
|
||||
if (clickLock.value) {
|
||||
event?.stopPropagation()
|
||||
return
|
||||
}
|
||||
|
||||
// 防抖:100ms 内重复点击忽略
|
||||
if (now - lastClickTime.value < 100) {
|
||||
event?.stopPropagation()
|
||||
return
|
||||
}
|
||||
|
||||
if (!userId) {
|
||||
event?.stopPropagation()
|
||||
return
|
||||
}
|
||||
|
||||
clickLock.value = true
|
||||
lastClickTime.value = now
|
||||
viewUserInfo(userId)
|
||||
|
||||
// 50ms 后释放点击锁
|
||||
setTimeout(() => {
|
||||
clickLock.value = false
|
||||
}, 50)
|
||||
|
||||
event?.stopPropagation()
|
||||
}
|
||||
|
||||
// 移动到中心位置
|
||||
const moveToCenter = (targetIndex, event) => {
|
||||
const now = Date.now()
|
||||
|
||||
// 点击锁检查
|
||||
if (clickLock.value) {
|
||||
event?.stopPropagation()
|
||||
return
|
||||
}
|
||||
|
||||
// 目标已是中心或正在移动中
|
||||
if (centerIndex.value == targetIndex || isMoving.value) {
|
||||
event?.stopPropagation()
|
||||
return
|
||||
}
|
||||
|
||||
// 防抖:100ms 内重复调用忽略
|
||||
if (now - lastClickTime.value < 100) {
|
||||
event?.stopPropagation()
|
||||
return
|
||||
}
|
||||
|
||||
clickLock.value = true
|
||||
isMoving.value = true
|
||||
centerIndex.value = targetIndex
|
||||
lastClickTime.value = now
|
||||
|
||||
updatePosition()
|
||||
|
||||
// 800ms 后释放锁(与 CSS transition 时间一致)
|
||||
setTimeout(() => {
|
||||
isMoving.value = false
|
||||
clickLock.value = false
|
||||
}, 800)
|
||||
|
||||
event?.stopPropagation()
|
||||
}
|
||||
|
||||
// 触摸开始
|
||||
const handleTouchStart = (event) => {
|
||||
touchStartX.value = event.touches[0].clientX
|
||||
isSwipe.value = false // 每次触摸开始重置滑动标记
|
||||
}
|
||||
|
||||
// 触摸移动
|
||||
const handleTouchMove = (event) => {
|
||||
if (!event.touches || event.touches.length === 0) return
|
||||
|
||||
touchEndX.value = event.touches[0].clientX
|
||||
const distance = touchEndX.value - touchStartX.value
|
||||
|
||||
// 滑动距离超过 10px 标记为滑动
|
||||
if (Math.abs(distance) > 10) {
|
||||
isSwipe.value = true
|
||||
}
|
||||
}
|
||||
|
||||
// 触摸结束
|
||||
const handleTouchEnd = (event) => {
|
||||
if (!touchStartX.value) {
|
||||
isSwipe.value = false
|
||||
return
|
||||
}
|
||||
|
||||
if (event.changedTouches && event.changedTouches.length > 0) {
|
||||
touchEndX.value = event.changedTouches[0].clientX
|
||||
}
|
||||
|
||||
const minSwipeDistance = 50
|
||||
const distance = touchEndX.value - touchStartX.value
|
||||
const isLeftSwipe = distance < -minSwipeDistance
|
||||
const isRightSwipe = distance > minSwipeDistance
|
||||
|
||||
// 先执行移动(此时 isSwipe 仍为 true)
|
||||
if (isLeftSwipe && centerIndex.value > 0) {
|
||||
moveToCenter(centerIndex.value - 1)
|
||||
} else if (isRightSwipe && centerIndex.value < seasonTop1List.value.length - 1) {
|
||||
moveToCenter(centerIndex.value + 1)
|
||||
}
|
||||
|
||||
// 最后重置触摸变量
|
||||
touchStartX.value = 0
|
||||
touchEndX.value = 0
|
||||
isSwipe.value = false
|
||||
}
|
||||
|
||||
// 更新位置
|
||||
const updatePosition = () => {
|
||||
const itemWidth = 40 // vw,根据您的代码中每个项目宽度
|
||||
const itemSpacing = 2 // vw,根据您的代码中项目间距
|
||||
const itemWidth = 40 // vw,每个项目宽度
|
||||
const itemSpacing = 2 // vw,项目间距
|
||||
const targetOffset = (itemWidth + itemSpacing) * centerIndex.value
|
||||
listLeftPosition.value = targetOffset + 'vw'
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user