@vueuse/gesture

repository·main·Indexed 19 days ago

https://github.com/vueuse/gesture

A collection of Vue composables and directives for mouse and touch interactions, including dragging, pinching, and scrolling. A Vue-compatible fork of react-use-gesture, it supports Vue 2 and Vue 3 via vue-demi. It provides built-in gesture types such as Drag (v-drag), Move (v-move), Hover (v-hover), Scroll (v-scroll), Wheel (v-wheel), and Pinch (v-pinch), and can be integrated with @vueuse/motion for spring-based animations.

Tokens
11.6K
Snippets
49
Records
59
Agent score
64%

What's inside @vueuse/gesture

  1. What is @vueuse/gesture

    main

    @vueuse/gesture is a collection of Vue Composables designed to add interactivity to Vue applications through pointer and touch gesture support. It is a Vue port of the react-use-gesture library from the Poimandres collective. The package provides gesture support via two primary interfaces:

    1. Composable functions: For logic-based integration within the Composition API.
    2. Directives: For template-based integration.
  2. Handling inertia in wheel events

    main

    Devices like the MacBook trackpad or Magic Mouse produce inertia. Because there is no native way to distinguish between an actual user wheel intent and the resulting inertia, you may need an external utility to detect intent.

    To detect actual intent and filter out inertia, it is recommended to use Lethargy.

  3. Understand the Gesture State object

    main

    When using a gesture handler in @vueuse/gesture, the callback function receives a state object. This object contains the original source event and enriched metadata about the gesture, such as velocity, movement deltas, and timing.

    While most attributes are consistent across different gesture types, usePinch and useDrag have specific distinctions which are documented on their respective pages. Most handlers provide access to position (xy), momentum (vxvy), and various offset/delta calculations.

    useXXXX((state) => {
      // Access gesture metadata via state
      const { xy, velocity, movement } = state;
    });
  4. Integrate @vueuse/gesture with @vueuse/motion using useSpring

    main

    To achieve smooth, organic gesture animations, you can combine @vueuse/gesture with @vueuse/motion.

    The recommended pattern is to use the useSpring composable from @vueuse/motion in conjunction with useMotionProperties. This allows you to bind reactive motion properties to a spring physics system. When you call the set() function returned by useSpring, any properties defined in your motion configuration will be animated using spring physics, while other properties will be updated immediately.

    // Get the element.
    const demoElement = ref()
    
    // Bind to the element or component reference
    // and init style properties that will be animated.
    const { motionProperties } = useMotionProperties(demoElement, {
      cursor: 'grab',
      x: 0,
      y: 0,
    })
    
    // Bind the motion properties to a spring reactive object.
    const { set } = useSpring(motionProperties)
    
    // Animatable values will be animated, the others will be changed immediately.
    const eventHandler = () => set({ x: 250, y: 200, cursor: 'default' })
  5. Install directives at the component level

    main

    If you only need specific directives in certain components, you can import the individual directive (e.g., dragDirective) and register it locally within the component's directives option.

    import { dragDirective } from '@vueuse/gesture'
    
    export default {
      directives: {
        drag: dragDirective,
      },
    }
  6. Use the usePinch composable

    main

    The usePinch composable allows you to track pinch gestures (distance and rotation between two pointers). It can be used via a Vue directive or as a composable. It works best on touch devices or laptop trackpads.

    To use it as a composable, pass a handler function and an options object containing the domTarget and eventOptions.

    <template>
      <div ref="demoBox" />
    </template>
    
    <script setup>
    import { usePinch } from '@vueuse/gesture'
    import { ref } from 'vue'
    
    const demoBox = ref()
    
    const pinchHandler = ({ offset: [d, a], pinching }) => {
      // d is distance, a is angle
      console.log('Distance:', d, 'Angle:', a, 'Is pinching:', pinching)
    }
    
    usePinch(pinchHandler, {
      domTarget: demoBox,
      eventOptions: {
        passive: true,
      },
    })
    </script>
  7. Configure gesture options for hooks and directives

    main

    The structure of your configuration object depends on which API you are using from @vueuse/gesture:

    1. Gesture-specific hooks (e.g., useDrag): Pass a single options object containing both generic and gesture-specific options.
    2. The useGesture hook: Pass a single options object where generic options are at the top level, and gesture-specific options are nested under their respective keys (e.g., drag, wheel, pinch).
    3. Directives (e.g., v-drag): Pass gesture-specific options to the directive (e.g., :drag-options). The domTarget is automatically handled by the directive.
    <template>
        <!-- Using Directives -->
        <div v-drag="dragHandler" :drag-options="dragOptions"></div
    </template>
    
    <script setup>
    // 1. Using a gesture-specific hook
    useDrag(state => doSomething(state), { ...genericOptions, ...dragOptions })
    
    // 2. Using the useGesture hook
    useGesture(state => doSomething(state), {
      ...genericOptions, // Global options
      drag:   dragOptions, // Gesture specific
      wheel:  wheelOptions,
      pinch:  pinchOptions,
      scroll: scrollOptions,
      hover:  hoverOptions,
    })
    
    // 3. Using gesture-specific directive
    const dragOptions = { ...genericOptions, ...dragOptions }
    const dragHandler = (gestureState) => doSomething(gestureState)
    </script>
  8. Use the v-pinch directive

    main

    You can apply pinch gesture tracking directly to an element using the v-pinch directive. Pass a handler function to the directive that receives the gesture state.

    <template>
      <!-- Directive usage -->
      <div v-pinch="pinchHandler" />
    </template>
    
    <script setup>
    const pinchHandler = ({ offset: [d, a], pinching }) => {
      // Handle the gesture state here
      console.log(d, a)
    }
    </script>
  9. Use the useDrag composable or v-drag directive

    main

    You can implement drag gestures in Vue using either the useDrag composable or the v-drag directive.

    When using the useDrag composable, you pass a handler function and an options object. The handler receives an object containing movement (an array of [x, y]) and dragging (a boolean indicating if the element is currently being dragged).

    When using the v-drag directive, you attach it to a template element and pass the handler function.

    <template>
      <!-- Directive usage -->
      <div ref="demo" v-drag="dragHandler" />
    </template>
    
    <script setup>
    const demo = ref()
    
    const dragHandler = ({ movement: [x, y], dragging }) => {
      if (!dragging) {
        // Reset position when drag ends
        set({ x: 0, y: 0, cursor: 'grab' })
        return
      }
    
      set({
        cursor: 'grabbing',
        x,
        y,
      })
    }
    
    // Composable usage
    useDrag(dragHandler, {
      domTarget: demo,
    })
    </script>
  10. Use the v-scroll directive

    main

    You can apply scroll tracking to an element using the v-scroll directive. Pass a handler function to the directive that receives the scroll state (including xy coordinates and other state properties).

    <template>
      <!-- Directive usage -->
      <div ref="demo" v-scroll="scrollHandler" />
    </template>
    
    <script setup>
    const demo = ref()
    
    const scrollHandler = ({ xy: [x, y], ...state }) => {
      // Handle scroll state here
    }
    </script>