In this tech blog , You will learn how to create or make a swipe component in vue js same like swiggy and zomato payment gateway button.
In order to make this functionality work ,we will use a vue package which is very popular and have many functionalities named as vue/usecore.
To make this functionality work let's start with creating the component :
npm i @vueuse/core
In this step we will create and make the component along with functionalites. After this we will let you know what is actually happening in this code with full explanations.
The code for this is:
<script setup lang="ts">
import { computed, ref } from 'vue'
import { usePointerSwipe } from '@vueuse/core'
import type { UseSwipeDirection } from '@vueuse/core'
const target = ref<HTMLElement | null>(null)
const container = ref<HTMLElement | null>(null)
const containerWidth = computed(() => container.value?.offsetWidth)
const left = ref('0')
const opacity = ref(1)
function reset() {
left.value = '0'
opacity.value = 1
}
const { distanceX, isSwiping } = usePointerSwipe(target, {
disableTextSelect: true,
onSwipe(e: PointerEvent) {
if (containerWidth.value) {
if (distanceX.value < 0) {
const distance = Math.abs(distanceX.value)
left.value = `${distance}px`
opacity.value = 1.25 - distance / containerWidth.value
}
else {
left.value = '0'
opacity.value = 1
}
}
},
onSwipeEnd(e: PointerEvent, direction: UseSwipeDirection) {
if (distanceX.value < 0 && containerWidth.value && (Math.abs(distanceX.value) / containerWidth.value) >= 0.5) {
left.value = '100%'
opacity.value = 0
}
else {
left.value = '0'
opacity.value = 1
}
},
})
</script>
<template>
<div ref="container" class="bg-gray-200 rounded relative w-full h-[80px] m-auto flex items-center justify-center overflow-hidden">
<button @click="reset">
Reset
</button>
<div
ref="target"
class="absolute w-full h-full top-0 left-0 bg-[#3eaf7c] flex items-center justify-center"
:class="{ 'transition-all duration-200 ease-linear': !isSwiping }"
:style="{ left, opacity }"
>
<p class="flex text-white items-center">
Swipe <mdi-arrow-right />
</p>
</div>
</div>
</template>
Explanations:
Imports and References:
import { computed, ref } from 'vue'
import { usePointerSwipe } from '@vueuse/core'
import type { UseSwipeDirection } from '@vueuse/core'
const target = ref<HTMLElement | null>(null)
const container = ref<HTMLElement | null>(null)
Computed Property:
const containerWidth = computed(() => container.value?.offsetWidth)
containerWidth
dynamically computes the width of the container.Reactive Properties:
const left = ref('0')
const opacity = ref(1)
left
controls the horizontal position of the green box.opacity
controls the opacity of the green box.
Reset Function:
function reset() {
left.value = '0'
opacity.value = 1
}
reset
function resets the left
and opacity
properties to their initial values.Swipe Handling:
const { distanceX, isSwiping } = usePointerSwipe(target, {
disableTextSelect: true,
onSwipe(e: PointerEvent) {
if (containerWidth.value) {
if (distanceX.value < 0) {
const distance = Math.abs(distanceX.value)
left.value = `${distance}px`
opacity.value = 1.25 - distance / containerWidth.value
} else {
left.value = '0'
opacity.value = 1
}
}
},
onSwipeEnd(e: PointerEvent, direction: UseSwipeDirection) {
if (distanceX.value < 0 && containerWidth.value && (Math.abs(distanceX.value) / containerWidth.value) >= 0.5) {
left.value = '100%'
opacity.value = 0
} else {
left.value = '0'
opacity.value = 1
}
},
})
usePointerSwipe
is used to handle the swipe gestures.distanceX
tracks the horizontal distance of the swipe.isSwiping
indicates whether a swipe is currently in progress.onSwipe
is called during the swipe, adjusting the left
and opacity
based on the swipe distance.onSwipeEnd
is called when the swipe ends, determining whether to slide the box off the screen based on swipe distance.
<template>
<div ref="container" class="bg-gray-200 rounded relative w-full h-[80px] m-auto flex items-center justify-center overflow-hidden">
<button @click="reset">
Reset
</button>
<div
ref="target"
class="absolute w-full h-full top-0 left-0 bg-[#3eaf7c] flex items-center justify-center"
:class="{ 'transition-all duration-200 ease-linear': !isSwiping }"
:style="{ left, opacity }"
>
<p class="flex text-white items-center">
Swipe <mdi-arrow-right />
</p>
</div>
</div>
</template>
<div>
element is the container with a gray background, rounded corners, and specific dimensions. It contains a reset button and the swiping element.<div>
(referred to by target
) is the element that moves when swiped. It has absolute positioning to allow free movement within the container.:class
binding adds a transition class to the swiping element when not swiping (isSwiping
is false) to enable smooth animations.:style
binding dynamically sets the left
and opacity
properties based on the swipe distance.
This component provides a visually interactive swipe feature where the green box moves and changes opacity based on user swipes. It includes a reset button to return the box to its original position. The swipe logic is handled using @vueuse/core
to track swipe distances and apply corresponding CSS transformations