From aef80c8b13afb76797225538524e22d007b89179 Mon Sep 17 00:00:00 2001 From: Adrien Foulon <6115458+Tofandel@users.noreply.github.com> Date: Mon, 28 Apr 2025 16:56:14 +0200 Subject: [PATCH] fix: allow users to pinch zoom on mobile and prevent click if user drags more than 10px --- playground/App.vue | 4 ++-- src/components/Carousel/Carousel.css | 2 +- src/components/Carousel/Carousel.ts | 5 +++++ src/composables/useDrag.ts | 20 ++++++++++++++------ 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/playground/App.vue b/playground/App.vue index 7243f72..cd97112 100644 --- a/playground/App.vue +++ b/playground/App.vue @@ -171,7 +171,7 @@ const handleReset = () => { items.splice(0, items.length, ...defaultSlides) } -const handelButtonClick = () => { +const handleButtonClick = () => { alert('Button clicked') } @@ -264,7 +264,7 @@ onMounted(() => { >
{{ item.description }}
- + diff --git a/src/components/Carousel/Carousel.css b/src/components/Carousel/Carousel.css index a016642..ae0ec56 100644 --- a/src/components/Carousel/Carousel.css +++ b/src/components/Carousel/Carousel.css @@ -7,7 +7,7 @@ height: var(--vc-carousel-height); overscroll-behavior: none; position: relative; - touch-action: pan-y; + touch-action: pan-x pan-y pinch-zoom; z-index: 1; } diff --git a/src/components/Carousel/Carousel.ts b/src/components/Carousel/Carousel.ts index c6c5a52..31f78c0 100644 --- a/src/components/Carousel/Carousel.ts +++ b/src/components/Carousel/Carousel.ts @@ -423,6 +423,11 @@ export const Carousel = defineComponent({ threshold, }) + // Prevent unnecessary reactivity + if (draggedSlides === 0) { + return + } + activeSlideIndex.value = config.wrapAround ? currentSlideIndex.value + draggedSlides : getNumberInRange({ diff --git a/src/composables/useDrag.ts b/src/composables/useDrag.ts index 1fc10c1..23ebcb7 100644 --- a/src/composables/useDrag.ts +++ b/src/composables/useDrag.ts @@ -35,7 +35,10 @@ export function useDrag(options: UseDragOptions) { isTouch = event.type === 'touchstart' - if (!isTouch) { + if (isTouch && (event as TouchEvent).touches.length > 1) { + // If there is more than 1 finger on the screen, avoid drag start (this allows user to pinch zoom) + return + } else if (!isTouch) { event.preventDefault() if ((event as MouseEvent).button !== 0) { return @@ -58,6 +61,10 @@ export function useDrag(options: UseDragOptions) { } const handleDrag = throttle((event: TouchEvent | MouseEvent): void => { + if (isTouch && (event as TouchEvent).touches.length > 1) { + return + } + isDragging.value = true const currentX = isTouch @@ -76,12 +83,13 @@ export function useDrag(options: UseDragOptions) { const handleDragEnd = (): void => { handleDrag.cancel() - if (!isTouch) { - const preventClick = (e: MouseEvent) => { + const draggedDistance = Math.abs(dragged.x) + Math.abs(dragged.y); + + if (!isTouch && draggedDistance > 10) { + window.addEventListener('click', (e: MouseEvent) => { e.preventDefault() - window.removeEventListener('click', preventClick) - } - window.addEventListener('click', preventClick) + e.stopPropagation() + }, { once: true, capture: true }) } options.onDragEnd?.()