添加 useTouch,统一处理手势判断

This commit is contained in:
icssoa
2025-11-13 22:31:11 +08:00
parent 4b381dc06b
commit ae977621cb
2 changed files with 29 additions and 26 deletions

View File

@@ -62,6 +62,7 @@
import { computed, ref, onMounted, watch, getCurrentInstance, type PropType } from "vue"; import { computed, ref, onMounted, watch, getCurrentInstance, type PropType } from "vue";
import { parsePt, parseRpx } from "@/cool"; import { parsePt, parseRpx } from "@/cool";
import type { PassThroughProps } from "../../types"; import type { PassThroughProps } from "../../types";
import { useTouch } from "../../hooks";
type Item = { type Item = {
url: string; url: string;
@@ -132,6 +133,7 @@ const props = defineProps({
const emit = defineEmits(["change", "item-tap"]); const emit = defineEmits(["change", "item-tap"]);
const { proxy } = getCurrentInstance()!; const { proxy } = getCurrentInstance()!;
const touch = useTouch();
// 透传属性类型定义 // 透传属性类型定义
type PassThrough = { type PassThrough = {
@@ -301,23 +303,21 @@ function startAutoplay() {
} }
} }
// 触摸起始Y坐标
let touchStartY = 0;
// 横向滑动参数
let touchHorizontal = 0;
/** /**
* 处理触摸开始事件 * 处理触摸开始事件
* 记录触摸起始状态,准备手势识别 * 记录触摸起始状态,准备手势识别
* @param e 触摸事件对象 * @param e 触摸事件对象
*/ */
function onTouchStart(e: TouchEvent) { function onTouchStart(e: UniTouchEvent) {
// 如果禁用触摸,则不进行任何操作 // 如果禁用触摸,则不进行任何操作
if (props.disableTouch) return; if (props.disableTouch) return;
// 单项或空列表不支持滑动 // 单项或空列表不支持滑动
if (props.list.length <= 1) return; if (props.list.length <= 1) return;
// 注册触摸开始事件
touch.start(e);
// 设置触摸状态 // 设置触摸状态
isTouching.value = true; isTouching.value = true;
@@ -327,8 +327,6 @@ function onTouchStart(e: TouchEvent) {
// 禁用动画,开始手势跟踪 // 禁用动画,开始手势跟踪
isAnimating.value = false; isAnimating.value = false;
touchStartPoint.value = e.touches[0].clientX; touchStartPoint.value = e.touches[0].clientX;
touchStartY = e.touches[0].clientY;
touchHorizontal = 0;
touchStartTimestamp.value = Date.now(); touchStartTimestamp.value = Date.now();
initialOffset.value = slideOffset.value; initialOffset.value = slideOffset.value;
} }
@@ -338,26 +336,14 @@ function onTouchStart(e: TouchEvent) {
* 实时更新容器位置,实现跟手效果 * 实时更新容器位置,实现跟手效果
* @param e 触摸事件对象 * @param e 触摸事件对象
*/ */
function onTouchMove(e: TouchEvent) { function onTouchMove(e: UniTouchEvent) {
if (props.list.length <= 1 || props.disableTouch || !isTouching.value) return; if (props.list.length <= 1 || props.disableTouch || !isTouching.value) return;
const x = touchStartPoint.value - e.touches[0].clientX; // 注册触摸移动事件
if (touchHorizontal == 0) { touch.move(e);
// 只在horizontal=0时判断一次
const y = touchStartY - e.touches[0].clientY;
if (Math.abs(x) > Math.abs(y)) {
// 如果x轴移动距离大于y轴移动距离则表明是横向移动手势
touchHorizontal = 1;
}
if (touchHorizontal == 1) {
// 如果是横向移动手势,则阻止默认行为(防止页面滚动)
e.preventDefault();
}
}
// 横向移动时才处理 // 横向移动时才处理
if (touchHorizontal != 1) { if (touch.horizontal != 1) {
return; return;
} }
@@ -373,8 +359,8 @@ function onTouchMove(e: TouchEvent) {
function onTouchEnd() { function onTouchEnd() {
if (props.list.length <= 1 || !isTouching.value) return; if (props.list.length <= 1 || !isTouching.value) return;
touchStartY = 0; // 注册触摸结束事件
touchHorizontal = 0; touch.end();
// 重置触摸状态 // 重置触摸状态
isTouching.value = false; isTouching.value = false;

View File

@@ -128,6 +128,7 @@ import { isAppIOS, isDark, isHarmony, parseClass, parsePt } from "@/cool";
import type { Justify, PassThroughProps } from "../../types"; import type { Justify, PassThroughProps } from "../../types";
import type { ClIconProps } from "../cl-icon/props"; import type { ClIconProps } from "../cl-icon/props";
import type { ClImageProps } from "../cl-image/props"; import type { ClImageProps } from "../cl-image/props";
import { useTouch } from "../../hooks";
defineOptions({ defineOptions({
name: "cl-list-item" name: "cl-list-item"
@@ -189,6 +190,7 @@ const props = defineProps({
const { proxy } = getCurrentInstance()!; const { proxy } = getCurrentInstance()!;
const slots = useSlots(); const slots = useSlots();
const touch = useTouch();
// 透传样式类型定义 // 透传样式类型定义
type PassThrough = { type PassThrough = {
@@ -278,6 +280,10 @@ const isHover = ref(false);
* @param e 触摸事件对象 * @param e 触摸事件对象
*/ */
function onTouchStart(e: UniTouchEvent) { function onTouchStart(e: UniTouchEvent) {
// 注册触摸开始事件
touch.start(e);
// 设置点击态
isHover.value = true; isHover.value = true;
// 记录开始触摸位置 // 记录开始触摸位置
@@ -292,6 +298,9 @@ function onTouchStart(e: UniTouchEvent) {
*/ */
function onTouchEnd() { function onTouchEnd() {
if (isHover.value) { if (isHover.value) {
// 注册触摸结束事件
touch.end();
// 计算滑动阈值 - 取滑动区域一半和50px中的较小值 // 计算滑动阈值 - 取滑动区域一半和50px中的较小值
const threshold = swipe.width / 2 > 50 ? 50 : swipe.width / 2; const threshold = swipe.width / 2 > 50 ? 50 : swipe.width / 2;
// 计算实际滑动距离 // 计算实际滑动距离
@@ -330,6 +339,14 @@ function onTouchCancel() {
*/ */
function onTouchMove(e: UniTouchEvent) { function onTouchMove(e: UniTouchEvent) {
if (isHover.value) { if (isHover.value) {
// 注册触摸移动事件
touch.move(e);
// 横向移动时才处理
if (touch.horizontal != 1) {
return;
}
// 计算滑动偏移量 // 计算滑动偏移量
const offsetX = (e.touches[0] as UniTouch).pageX - swipe.startX; const offsetX = (e.touches[0] as UniTouch).pageX - swipe.startX;