You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否用jQuery UI resizable/draggable实现拖拽绘制式创建新DOM元素?

Implement Drag-to-Draw Resizable/Draggable Divs (Like Awwapp's Rectangle Tool)

Got it, let's build that intuitive drag-to-create workflow you're after—replacing the click-to-generate behavior with a drag-to-draw interaction for your resizable/draggable divs. Below is a complete, vanilla JS implementation you can drop into your project (or adapt if you're using a library like jQuery UI for existing drag/resize logic):


Step 1: Basic HTML Structure

First, set up your canvas container where users will draw divs:

<div id="canvas-container">
  <!-- Dynamically generated divs will live here -->
</div>

Step 2: CSS for Styling & Interaction

Add styles to turn the container into a drawing surface, and style the draggable/resizable divs (including a resize handle):

#canvas-container {
  width: 100vw;
  height: 100vh;
  position: relative;
  background-color: #f5f5f5;
  cursor: crosshair; /* Visual cue for drawing mode */
}

.draggable-resizable {
  position: absolute;
  border: 2px solid #2196F3;
  background-color: rgba(33, 150, 243, 0.1);
  cursor: move;
}

.resize-handle {
  position: absolute;
  width: 15px;
  height: 15px;
  background-color: #2196F3;
  bottom: 0;
  right: 0;
  cursor: se-resize;
}

Step 3: JavaScript Logic for Drag-to-Draw & Interaction

This handles the drawing workflow, plus adds drag and resize functionality to finished divs:

const canvas = document.getElementById('canvas-container');
let isDrawing = false;
let tempDiv = null;
let startX, startY;

// Start drawing on mouse down
canvas.addEventListener('mousedown', (e) => {
  isDrawing = true;
  startX = e.clientX;
  startY = e.clientY;

  // Create temporary div for drawing preview
  tempDiv = document.createElement('div');
  tempDiv.classList.add('draggable-resizable');
  tempDiv.style.left = `${startX}px`;
  tempDiv.style.top = `${startY}px`;
  tempDiv.style.width = '0px';
  tempDiv.style.height = '0px';

  // Add resize handle (we'll make it functional after creation)
  const resizeHandle = document.createElement('div');
  resizeHandle.classList.add('resize-handle');
  tempDiv.appendChild(resizeHandle);

  canvas.appendChild(tempDiv);
});

// Update div size during mouse move
canvas.addEventListener('mousemove', (e) => {
  if (!isDrawing || !tempDiv) return;

  // Calculate dimensions (handle left/up drags with min values)
  const width = Math.abs(e.clientX - startX);
  const height = Math.abs(e.clientY - startY);
  const left = Math.min(e.clientX, startX);
  const top = Math.min(e.clientY, startY);

  // Update temp div position and size
  tempDiv.style.left = `${left}px`;
  tempDiv.style.top = `${top}px`;
  tempDiv.style.width = `${width}px`;
  tempDiv.style.height = `${height}px`;
});

// Finish drawing on mouse up
canvas.addEventListener('mouseup', () => {
  if (!isDrawing || !tempDiv) return;

  isDrawing = false;

  // Skip tiny accidental divs (adjust threshold as needed)
  const width = parseInt(tempDiv.style.width);
  const height = parseInt(tempDiv.style.height);
  if (width < 10 || height < 10) {
    tempDiv.remove();
    return;
  }

  // Add drag and resize functionality to the finished div
  makeDraggable(tempDiv);
  makeResizable(tempDiv);

  tempDiv = null;
});

// Clean up if mouse leaves canvas mid-draw
canvas.addEventListener('mouseleave', () => {
  if (isDrawing && tempDiv) {
    tempDiv.remove();
    isDrawing = false;
    tempDiv = null;
  }
});

// Helper: Make a div draggable
function makeDraggable(element) {
  let isDragging = false;
  let offsetX, offsetY;

  element.addEventListener('mousedown', (e) => {
    if (e.target.classList.contains('resize-handle')) return; // Ignore resize handle for drag
    isDragging = true;
    offsetX = e.clientX - parseInt(element.style.left);
    offsetY = e.clientY - parseInt(element.style.top);
    element.style.zIndex = 100; // Bring to front while dragging
  });

  document.addEventListener('mousemove', (e) => {
    if (!isDragging) return;
    element.style.left = `${e.clientX - offsetX}px`;
    element.style.top = `${e.clientY - offsetY}px`;
  });

  document.addEventListener('mouseup', () => {
    if (isDragging) {
      isDragging = false;
      element.style.zIndex = 1; // Reset z-index
    }
  });
}

// Helper: Make a div resizable via its handle
function makeResizable(element) {
  const handle = element.querySelector('.resize-handle');
  let isResizing = false;
  let startWidth, startHeight, offsetX, offsetY;

  handle.addEventListener('mousedown', (e) => {
    isResizing = true;
    startWidth = parseInt(element.style.width);
    startHeight = parseInt(element.style.height);
    offsetX = e.clientX;
    offsetY = e.clientY;
    element.style.zIndex = 100; // Bring to front while resizing
    e.stopPropagation(); // Prevent triggering drag
  });

  document.addEventListener('mousemove', (e) => {
    if (!isResizing) return;
    const newWidth = startWidth + (e.clientX - offsetX);
    const newHeight = startHeight + (e.clientY - offsetY);
    // Enforce minimum size
    element.style.width = `${Math.max(newWidth, 10)}px`;
    element.style.height = `${Math.max(newHeight, 10)}px`;
  });

  document.addEventListener('mouseup', () => {
    if (isResizing) {
      isResizing = false;
      element.style.zIndex = 1; // Reset z-index
    }
  });
}

Key Details Explained

  • Drag-to-Draw Flow: We create a temporary div on mousedown, update its size/position in real-time during mousemove, and finalize it on mouseup.
  • Negative Coordinate Handling: When users drag left or up from the starting point, we use Math.min to keep the div positioned correctly.
  • Minimum Size Check: Prevents tiny, accidental divs from cluttering the canvas (adjust the threshold in the mouseup handler as needed).
  • Drag/Resize Isolation: The resize handle doesn't trigger drag events thanks to e.stopPropagation(), and we adjust z-index to keep the active element on top.

If you're already using a library like jQuery UI or interact.js for drag/resize, you can replace the makeDraggable and makeResizable helpers with the library's methods—this vanilla implementation is just a self-contained example.

内容的提问来源于stack exchange,提问作者dom_ahdigital

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 03:32:06