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

React实现从菜单拖拽元素到指定区域并在区内拖动的问题

Solution: Implement Drag-and-Drop Copy + Boundary Restriction with react-rnd

Hey there, let's tackle this drag-and-drop problem you're facing with react-rnd! From what I've gathered, your core requirements are:

  • Drag elements from a menu to a target area while keeping the original element in the menu
  • Ensure the cloned element can only move within the target area (no lingering between the menu and target)

Here's a step-by-step implementation based on your existing code:

1. Add State & Refs for Tracking

First, we need state to manage the cloned elements in the target area, plus refs to track drag offsets and the target container's dimensions:

import React, { useState, useRef } from "react";
import "./styles.css";
import { Rnd } from "react-rnd";

const elementStyle = { 
  display: "flex", 
  alignItems: "center", 
  justifyContent: "center", 
  border: "solid 1px #ddd", 
  background: "#f0f0f0", 
  position: "absolute" 
};

export default function App() {
  // Track all cloned elements in the target area
  const [targetElements, setTargetElements] = useState([]);
  // Store mouse offset relative to the dragged element's top-left corner
  const dragOffsetRef = useRef({ x: 0, y: 0 });
  // Reference to the target container to get its position/size
  const targetContainerRef = useRef(null);

2. Implement Drag Copy Logic

Add handlers to the menu's Rnd component to clone elements when the drag ends inside the target area:

const handleDragStart = (e, dragData) => {
    // Calculate where the mouse is relative to the element's origin
    dragOffsetRef.current = {
      x: e.clientX - dragData.x,
      y: e.clientY - dragData.y
    };
  };

  const handleDragStop = (e) => {
    const targetRect = targetContainerRef.current.getBoundingClientRect();
    // Check if the mouse was released inside the target container
    const isDropInTarget = 
      e.clientX >= targetRect.left && 
      e.clientX <= targetRect.right &&
      e.clientY >= targetRect.top &&
      e.clientY <= targetRect.bottom;

    if (isDropInTarget) {
      // Calculate the element's position relative to the target container
      const relativeX = e.clientX - targetRect.left - dragOffsetRef.current.x;
      const relativeY = e.clientY - targetRect.top - dragOffsetRef.current.y;
      // Add a new cloned element to the target area
      setTargetElements(prev => [...prev, { id: Date.now(), x: relativeX, y: relativeY }]);
    }
  };

3. Render Menu & Target Area

Update the JSX to render the menu (with the original element) and target area (with cloned, bounded elements):

return (
    <div className="App">
      {/* Menu Area - Original element stays here, triggers drag copy */}
      <div style={{ height: 150, border: "1px solid #000", position: "relative" }}>
        <Rnd
          style={elementStyle}
          handle=".drag-handle"
          default={{ x: 0, y: 0, width: 100, height: 50 }}
          draggableProps={{ allowAnyClick: true }}
          onDragStart={handleDragStart}
          onDragStop={handleDragStop}
        >
          <div className="drag-handle">Drag Me</div>
        </Rnd>
      </div>

      {/* Target Area - Cloned elements are locked here */}
      <div 
        ref={targetContainerRef}
        style={{ 
          height: 300, 
          border: "1px solid #000", 
          position: "relative",
          marginTop: 20
        }}
      >
        {targetElements.map(element => (
          <Rnd
            key={element.id}
            style={elementStyle}
            handle=".drag-handle"
            bounds="parent" // Forces element to stay within the target container
            position={{ x: element.x, y: element.y }}
            default={{ width: 100, height: 50 }}
            draggableProps={{ allowAnyClick: true }}
          >
            <div className="drag-handle">Cloned Element</div>
          </Rnd>
        ))}
      </div>
    </div>
  );
}

Key Details to Note

  • Drag Copy: We don't move the original element—instead, we clone it when the drag ends inside the target area. The original stays in the menu.
  • Boundary Lock: Setting bounds="parent" on the target area's Rnd components ensures they can never be dragged outside the target container.
  • Position Accuracy: We calculate the mouse offset during drag start to make sure the cloned element appears exactly where you release the mouse.

This setup will match the behavior you're aiming for!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 11:02:41