瀏覽代碼

修改 cl-banner 第三张后图片不显示问题

icssoa 5 月之前
父節點
當前提交
5157026002
共有 1 個文件被更改,包括 66 次插入31 次删除
  1. 66 31
      uni_modules/cool-ui/components/cl-banner/cl-banner.uvue

+ 66 - 31
uni_modules/cool-ui/components/cl-banner/cl-banner.uvue

@@ -177,6 +177,12 @@ const touchStartTimestamp = ref(0);
 /** 触摸开始时的初始偏移量 */
 const initialOffset = ref(0);
 
+/** 是否正在触摸中 */
+const isTouching = ref(false);
+
+/** 位置更新防抖定时器 */
+let positionUpdateTimer: number = 0;
+
 /**
  * 更新轮播容器的位置
  * 根据当前激活索引计算并设置容器的偏移量
@@ -184,22 +190,32 @@ const initialOffset = ref(0);
 function updateSlidePosition() {
 	if (bannerWidth.value == 0) return;
 
-	// 计算累积偏移量,考虑每个位置的动态边距
-	let totalOffset = 0;
-
-	// 遍历当前索引之前的所有项,累加它们的宽度
-	for (let i = 0; i < activeIndex.value; i++) {
-		const itemPreviousMargin = i == 0 ? 0 : props.previousMargin;
-		const itemNextMargin = i == props.list.length - 1 ? 0 : props.nextMargin;
-		const itemWidthAtIndex = bannerWidth.value - itemPreviousMargin - itemNextMargin;
-		totalOffset += itemWidthAtIndex;
+	// 防抖处理,避免频繁更新
+	if (positionUpdateTimer != 0) {
+		clearTimeout(positionUpdateTimer);
 	}
 
-	// 当前项的左边距
-	const currentPreviousMargin = activeIndex.value == 0 ? 0 : props.previousMargin;
+	// @ts-ignore
+	positionUpdateTimer = setTimeout(() => {
+		// 计算累积偏移量,考虑每个位置的动态边距
+		let totalOffset = 0;
+
+		// 遍历当前索引之前的所有项,累加它们的宽度
+		for (let i = 0; i < activeIndex.value; i++) {
+			const itemPreviousMargin = i == 0 ? 0 : props.previousMargin;
+			const itemNextMargin = i == props.list.length - 1 ? 0 : props.nextMargin;
+			const itemWidthAtIndex = bannerWidth.value - itemPreviousMargin - itemNextMargin;
+			totalOffset += itemWidthAtIndex;
+		}
 
-	// 设置最终的偏移量:负方向移动累积宽度,然后加上当前项的左边距
-	slideOffset.value = -totalOffset + currentPreviousMargin;
+		// 当前项的左边距
+		const currentPreviousMargin = activeIndex.value == 0 ? 0 : props.previousMargin;
+
+		// 设置最终的偏移量:负方向移动累积宽度,然后加上当前项的左边距
+		slideOffset.value = -totalOffset + currentPreviousMargin;
+
+		positionUpdateTimer = 0;
+	}, 10);
 }
 
 /**
@@ -262,18 +278,24 @@ function startAutoplay() {
 
 	if (props.autoplay) {
 		clearAutoplay();
-	}
 
-	isAnimating.value = true;
-
-	// @ts-ignore
-	autoplayTimer = setInterval(() => {
-		if (activeIndex.value >= props.list.length - 1) {
-			activeIndex.value = 0;
-		} else {
-			activeIndex.value++;
+		// 只有在非触摸状态下才启动自动轮播
+		if (!isTouching.value) {
+			isAnimating.value = true;
+
+			// @ts-ignore
+			autoplayTimer = setInterval(() => {
+				// 再次检查是否在触摸中,避免触摸时自动切换
+				if (!isTouching.value) {
+					if (activeIndex.value >= props.list.length - 1) {
+						activeIndex.value = 0;
+					} else {
+						activeIndex.value++;
+					}
+				}
+			}, props.interval);
 		}
-	}, props.interval);
+	}
 }
 
 /**
@@ -281,13 +303,16 @@ function startAutoplay() {
  * 记录触摸起始状态,准备手势识别
  * @param e 触摸事件对象
  */
-function onTouchStart(e: UniTouchEvent) {
+function onTouchStart(e: TouchEvent) {
 	// 如果禁用触摸,则不进行任何操作
 	if (props.disableTouch) return;
 
 	// 单项或空列表不支持滑动
 	if (props.list.length <= 1) return;
 
+	// 设置触摸状态
+	isTouching.value = true;
+
 	// 清除自动轮播
 	clearAutoplay();
 
@@ -303,8 +328,8 @@ function onTouchStart(e: UniTouchEvent) {
  * 实时更新容器位置,实现跟手效果
  * @param e 触摸事件对象
  */
-function onTouchMove(e: UniTouchEvent) {
-	if (props.list.length <= 1 || props.disableTouch) return;
+function onTouchMove(e: TouchEvent) {
+	if (props.list.length <= 1 || props.disableTouch || !isTouching.value) return;
 
 	// 计算手指移动距离,实时更新偏移量
 	const deltaX = e.touches[0].clientX - touchStartPoint.value;
@@ -316,7 +341,10 @@ function onTouchMove(e: UniTouchEvent) {
  * 根据滑动距离和速度判断是否切换轮播项
  */
 function onTouchEnd() {
-	if (props.list.length <= 1) return;
+	if (props.list.length <= 1 || !isTouching.value) return;
+
+	// 重置触摸状态
+	isTouching.value = false;
 
 	// 恢复动画效果
 	isAnimating.value = true;
@@ -324,7 +352,7 @@ function onTouchEnd() {
 	// 计算滑动距离、时间和速度
 	const deltaX = slideOffset.value - initialOffset.value;
 	const deltaTime = Date.now() - touchStartTimestamp.value;
-	const velocity = Math.abs(deltaX) / deltaTime; // px/ms
+	const velocity = deltaTime > 0 ? Math.abs(deltaX) / deltaTime : 0; // px/ms
 
 	let newIndex = activeIndex.value;
 
@@ -343,9 +371,14 @@ function onTouchEnd() {
 		}
 	}
 
-	// 更新索引
-	activeIndex.value = newIndex;
-	updateSlidePosition();
+	// 更新索引 - 如果索引没有变化,需要手动恢复位置
+	if (newIndex == activeIndex.value) {
+		// 索引未变化,恢复到正确位置
+		updateSlidePosition();
+	} else {
+		// 索引变化,watch会自动调用updateSlidePosition
+		activeIndex.value = newIndex;
+	}
 
 	// 恢复自动轮播
 	setTimeout(() => {
@@ -379,6 +412,8 @@ onMounted(() => {
 
 	&__list {
 		@apply flex flex-row h-full w-full overflow-visible;
+		// HBuilderX 4.8.2 bug,临时处理
+		width: 100000px;
 
 		&.is-transition {
 			transition-property: transform;