Skip to content

Drag Directive

v-tui-drag is a general-purpose drag enhancement directive in TechUI. It allows developers to turn any DOM element into a draggable state via a configuration object. This directive not only supports conventional absolute positioning dragging but is also deeply optimized for the transform performance mode and features built-in coordinate correction logic for large-screen scaling scenarios (Adaptive).

Core Features

  • Dual Mode Positioning: Supports two movement modes: transform (GPU accelerated, default) and style.left/top (Absolute positioning).
  • Fine-grained Control: Supports specifying a drag handle (trigger) and excluded areas (exclude).
  • Boundary Constraints: Automatically restricts element movement within the parent container's scope (containment).
  • Scale Adaptation: Built-in inAdpt parameter to solve the issue of desynchronization between mouse displacement and element movement under the large-screen scale mode.

Basic Usage

The simplest usage is to bind the directive directly. It enables containment and uses transform for movement by default.

vue
<template>
  <div class="box" v-tui-drag>
    Drag Me
  </div>
</template>

API Reference

v-tui-drag accepts an object as a parameter, supporting the following configuration options:

Parameter NameDescriptionTypeDefault
enabledEnable Switch. Controls whether dragging is allowed. It automatically handles cursor styles when dynamically switched.Booleantrue
triggerDrag Handle. CSS selector string. Dragging is triggered only when the mouse is pressed on the specified child element (e.g., allow dragging only by holding the title bar).Stringel (Self)
excludeExcluded Area. CSS selector string. Elements located inside the trigger that do not trigger dragging (e.g., the close button on the title bar).String
containmentBoundary Constraint. Whether to restrict the element within the visible range of the parent container.Booleantrue
positionTypePositioning Mode. Options: 'transform' or 'absolute'/'fixed'.
'transform': Modifies CSS Translate, better performance, does not break document flow.
'absolute': Modifies left/top, suitable for traditional positioning layouts.
String'transform'
inAdptScale Correction. Whether it is inside a TechUI scaling adaptive container. When enabled, it corrects mouse coordinates based on the global tDom.adpt.info to prevent drag drift.Booleanfalse
resetOnDisableReset on Disable. Whether to clear the element's style attributes (e.g., reset position) when enabled becomes false.Booleanfalse
uidEvent ID. Used to distinguish different event listeners. Recommended to pass a unique ID in complex scenarios.String

Typical Cases

Here are typical use cases for the v-tui-drag directive in the TechUI component library.

Dialog Component (Dialog)

This is the most classic usage scenario. Usually, we want:

  • The user can only drag by holding the Title Bar (.dialog-header).
  • Clicking the Close Button (.dialog-close) does not trigger dragging.
  • Dragging is disabled in Fullscreen mode (fullscreen).
  • Restrict the dialog from being dragged out of the visible area.
vue
<template>
  <div 
    class="dialog-inner"
    v-tui-drag="{ 
      enabled: draggable && !fullscreen, // Disable when fullscreen or configured as not draggable
      trigger: '.dialog-header',         // Only the title bar is draggable
      exclude: '.dialog-close',          // Exclude the close button to prevent accidental triggering
      containment: true,                 // Restrict within the parent container
      positionType: 'absolute',          // Use absolute positioning mode (matches dialog CSS)
      inAdpt: isInsideAdaptiveBox,       // Enable correction if inside a scaling container
      uid: uniqueId
    }"
  >
    <div class="dialog-header">
      <span>Title</span>
      <button class="dialog-close">X</button>
    </div>
    <div class="dialog-content">...</div>
  </div>
</template>

Global Adaptive Container (Adaptive Container)

In data dashboard or editor scenarios, you may need to drag the entire canvas.

  • Use positionType: 'transform' here to get the best rendering performance.
  • Enable resetOnDisable: true to automatically reset the position when the canvas is locked.
vue
<template>
  <div 
    id="tuiAdptOuter"
    v-tui-drag="{ 
      enabled: state.dragable,       // Controlled by state whether it is draggable
      trigger: '#tuiAdpt',           // The entire area serves as the handle
      resetOnDisable: true,          // Reset transform position when disabled
      containment: false,            // No boundary restriction, allow dragging out of view
      positionType: 'transform',     // Use GPU acceleration for movement
      inAdpt: false,                 // It is the adaptive layer itself, no need for correction
      uid: 'adpt-drag-001'
    }"
  >
    </div>
</template>

Technical Details

Coordinate Calculation Logic

The directive implements complex coordinate calculation internally via drag.js:

  1. Get Start Position (getStartPosition):
  • Transform Mode: Parses window.getComputedStyle(el).transform matrix (DOMMatrix) to get the current translate X/Y.
  • Position Mode: Calculates the offset of el.getBoundingClientRect() relative to offsetParent.
  1. Movement Delta: Calculates e.clientX - mouseStartX. If inAdpt is enabled, the delta is divided by the global scale factors (scaleX, scaleY) to ensure the mouse stays synchronized with the element in a scaled page.
  2. Boundary Collision (containCalcTrans/containCalcPos): Pre-calculates the minimum and maximum allowed X/Y values and performs numerical clamping (Clamp) during mousemove.

Released under the MIT License.