Procházet zdrojové kódy

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

icssoa před 4 měsíci
rodič
revize
ae977621cb

+ 12 - 26
uni_modules/cool-ui/components/cl-banner/cl-banner.uvue

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

+ 17 - 0
uni_modules/cool-ui/components/cl-list-item/cl-list-item.uvue

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