Loading...

How to make swipe button in vue js

Image

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 : 

Step  First : Install vue/usecore package

npm i @vueuse/core

Step Second : Create a vue component and do the functionality

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: 

Script Section

 

  1. 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)
  2. Computed Property:  

    const containerWidth = computed(() => container.value?.offsetWidth)
    1. containerWidth dynamically computes the width of the container.
  3. Reactive Properties:

    const left = ref('0')
    const opacity = ref(1)
    1. left controls the horizontal position of the green box.
    2. opacity controls the opacity of the green box.

       

  4. Reset Function:

    function reset() {
      left.value = '0'
      opacity.value = 1
    }
    1. The reset function resets the left and opacity properties to their initial values.
  5. 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
        }
      },
    })
    1. usePointerSwipe is used to handle the swipe gestures.
    2. distanceX tracks the horizontal distance of the swipe.
    3. isSwiping indicates whether a swipe is currently in progress.
    4. onSwipe is called during the swipe, adjusting the left and opacity based on the swipe distance.
    5. onSwipeEnd is called when the swipe ends, determining whether to slide the box off the screen based on swipe distance.

     

 

Template Section

<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>

 

  • The outer <div> element is the container with a gray background, rounded corners, and specific dimensions. It contains a reset button and the swiping element.
  • The inner <div> (referred to by target) is the element that moves when swiped. It has absolute positioning to allow free movement within the container.
  • The :class binding adds a transition class to the swiping element when not swiping (isSwiping is false) to enable smooth animations.
  • The :style binding dynamically sets the left and opacity properties based on the swipe distance.

 

Summary

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

0 Comments

Leave a comment