interact.js

repository·main·Indexed 12 days ago

https://github.com/taye/interact.js

A powerful JavaScript library for handling drag and drop, resizing, and multi-touch gestures. It supports inertia, snapping, and works across modern browsers and Internet Explorer 9+. Version 1.10.28 provides features such as dropzones with overlap detection, axis locking for draggable elements, and custom cursor styling.

Tokens
39.9K
Snippets
142
Records
179
Agent score
95%

What's inside interact.js

  1. Handle inertia resumption with the resume event

    main

    When a user resumes an action during the inertia phase (if allowResume is enabled), the difference between the start and resume coordinates relative to the target's top-left corner is not automatically reflected in the subsequent {action}move events.

    To account for this coordinate difference, you must listen for the {action}resume event (e.g., dragresume or resizeresume) and handle it similarly to how you would handle an {action}move event.

  2. Control drag axis with startAxis and lockAxis

    main

    You can restrict the direction of a drag action using startAxis and lockAxis options:

    • startAxis: Defines the required direction of the initial movement to trigger the drag. Use 'x' for horizontal or 'y' for vertical.
    • lockAxis: Restricts subsequent drag events to a specific axis.
      • Setting lockAxis: 'start' locks the movement to the direction established by the startAxis.
      • You can also lock to a specific axis like 'x' or 'y'.
    // lock the drag to the starting direction
    interact(singleAxisTarget).draggable({
      startAxis: 'xy'
      lockAxis: 'start'
    });
    
    // only drag if the drag was started horizontally
    interact(horizontalTarget).draggable({
      startAxis: 'x'
      lockAxis: 'x'
    });
  3. Use @interactjs/dev-tools for development

    main

    The @interactjs/dev-tools package provides development-time hints to help avoid common issues, such as missing event handlers, and provides useful CSS styles.

    Note: You should avoid including these development hints in your production deployment to keep your bundle optimized.

  4. Use modifiers to transform action event coordinates

    main

    Modifiers allow you to change the coordinates of action events (like dragmove). You can pass an array of modifiers to an action method (e.g., .draggable({ modifiers: [...] })).

    Important: Modifiers in the array are applied sequentially, and their order can affect the final result.

    const restrictToParent = interact.modifiers.restrict({
      restriction: 'parent',
      elementRect: { left: 0, right: 0, top: 1, bottom: 1 },
    })
    
    const snap100x100 = interact.modifiers.snap({
      targets: [interact.snappers.grid({ x: 100, y: 100 })],
      relativePoints: [{ x: 0.5, y: 0.5 }],
    })
    
    interact(target)
      .draggable({
        modifiers: [restrictToParent, snap100x100],
      })
      .on('dragmove', event => console.log(event.pageX, event.pageY))
  5. Understand the three basic action types in interact.js

    main

    interact.js categorizes pointer interactions (down → move → up sequences) into three primary action types:

    • Draggable: Used for moving elements or drawing on a canvas. This can be paired with dropzones to create drag-and-drop interfaces.
    • Resizable: Used to monitor and control the size and position of an element by interacting with its edges.
    • Gesturable: Used for multi-touch (2-finger) gestures, providing data such as angle and scale.

    Note: Advanced features like Sortable and Swappable (for list reordering) are available in the Pro version and are built upon the draggable action.

  6. How dropzones work in interact.js

    main

    Dropzones are elements that act as targets for draggable elements. When a draggable element is dropped into a dropzone, interact.js fires drop events.

    Important: Drop events do not automatically modify the DOM (e.g., they won't re-parent the dragged element into the dropzone). You must implement your own DOM manipulation logic within your event listeners if you want the element to physically move in the document structure.

    interact(dropTarget)
      .dropzone({
        ondrop: function (event) {
          alert(event.relatedTarget.id
                + ' was dropped into '
                + event.target.id)
        }
      })
      .on('dropactivate', function (event) {
        event.target.classList.add('drop-activated')
      })
  7. Make an element draggable with interact.js

    main

    To enable dragging on an element, use the interact(target).draggable(options) method. You must provide a listeners object containing event handlers, typically for move to update the element's position.

    Important CSS Requirements: To ensure smooth interaction and prevent browser interference, apply the following CSS to your draggable elements:

    • touch-action: none: Prevents the browser from panning/scrolling when using touch pointers.
    • user-select: none: Prevents text selection during the drag action.

    Drag Event Properties: In addition to standard InteractEvent properties, dragmove events include:

    • dragEnter: The dropzone this Interactable was dragged over.
    • dragLeave: The dropzone this Interactable was dragged out of.
    const position = { x: 0, y: 0 }
    
    interact('.draggable').draggable({
      listeners: {
        start (event) {
          console.log(event.type, event.target)
        },
        move (event) {
          position.x += event.dx
          position.y += event.dy
    
          event.target.style.transform = `translate(${position.x}px, ${position.y}px)`
        },
      },
    })
  8. How to get started with interact.js

    main

    To implement interactions with interact.js, follow these three core steps:

    1. Create an Interactable target: Use the interact() function with a CSS selector or a DOM element.
    2. Configure actions and modifiers: Enable specific behaviors like draggable(), resizable(), or gesturable() and add options like inertia or modifiers (e.g., for snapping or restricting movement).
    3. Add event listeners: Since interact.js does not move elements automatically by default, you must add event listeners (like dragmove) to manually update the element's styles or your application state.

    Note: If you require built-in hardware-accelerated feedback or framework components (Vue/React), consider interact.js Pro.

    // 1. Target elements
    const slider = interact('.slider')
    
    slider
      // 2. Configure actions
      .draggable({
        origin: 'self',
        inertia: true,
        modifiers: [
          interact.modifiers.restrict({
            restriction: 'self',
          }),
        ],
      })
      // 3. Add event listeners for visual feedback
      .on('dragmove', function (event) {
        // Manually update styles/state
        const sliderWidth = interact.getElementRect(event.target.parentNode).width
        const value = event.pageX / sliderWidth
        event.target.style.paddingLeft = (value * 100) + '%'
        event.target.setAttribute('data-value', value.toFixed(2))
      })
  9. Prevent scrolling during touch interactions

    main

    To allow touch-based dragging or resizing without triggering default browser behaviors like scrolling or zooming, apply the touch-action: none CSS property to your draggable and resizable elements.

    .draggable, .resizable, .gesturable {
      -ms-touch-action: none;
      touch-action: none;
      user-select: none;
    }
  10. Calculate total movement using X0 and Y0

    main

    In recent versions, the dx and dy fields on dragend, resizeend, and gestureend events no longer represent the total difference between the start and end coordinates. Instead, they represent the difference between the end event and the last move event (and are thus often 0).

    To calculate the total distance moved from the start of the action, use event.X0 and event.Y0 (or event.clientX0 and event.clientY0) and subtract them from the current event coordinates.

    interact(target).draggable({
      onend: function (event) {
        // Calculate total displacement from start
        const totalDx = event.pageX - event.X0;
        const totalDy = event.pageY - event.Y0;
        console.log(totalDx, totalDy);
      },
    })
    interact(target).draggable({
      onend: function (event) {
        console.log(event.pageX - event.X0, event.pageY - event.Y0)
      },
    })
  11. Install interact.js

    main

    You can install interactjs using npm, via CDN, or through package managers for specific frameworks like Rails or Webjars.

    npm

    npm install interactjs

    jsDelivr CDN

    <script src="https://cdn.jsdelivr.net/npm/interactjs/dist/interact.min.js"></script>

    unpkg CDN

    <script src="https://unpkg.com/interactjs/dist/interact.min.js"></script>

    Rails 5.1+

    1. Run yarn add interactjs
    2. Add //= require interactjs/interact to your asset manifest.

    Webjars SBT/Play 2

    Add the following to your dependencies: libraryDependencies ++= Seq("org.webjars.npm" % "interactjs" % version)