react可视化编辑器 第三章 限制移动范围

慈云数据 2024-03-20 技术支持 72 0

在这里插入图片描述

代码

import React, {
  useState,
  DragEvent,
  useRef,
  useEffect,
  MouseEvent,
} from 'react';
// import { throttle } from 'lodash';
interface Demo {
  id: number;
  x: number;
  y: number;
}
const App: React.FC = () => {
  const [demos, setDemos] = useState([]);
  // let currentDiv: HTMLDivElement | null = null;
  const divRef = useRef(null);
  const handleDragStart = (e: DragEvent, id: number) => {
    e.dataTransfer.setData('text/plain', id.tostring());
    const offsetX = e.clientX - e.currentTarget.getBoundingClientRect().left;
    const offsetY = e.clientY - e.currentTarget.getBoundingClientRect().top;
    e.dataTransfer.setData('offsetX', offsetX.toString());
    e.dataTransfer.setData('offsetY', offsetY.toString());
  };
  const handleDrop = (e: DragEvent) => {
    e.preventDefault();
    const clientX = e.clientX;
    const clientY = e.clientY;
    const contentStyle = document
      .getElementById('content')
      .getBoundingClientRect();
    const offsetX = e.dataTransfer.getData('offsetX');
    const offsetY = e.dataTransfer.getData('offsetY');
    const x = clientX - contentStyle.left - offsetX;
    const y = clientY - contentStyle.top - offsetY;
    const newDemo: Demo = { x, y, id: +new Date() };
    setDemos([...demos, newDemo]);
  };
  const handleDragOver = (e: DragEvent) => {
    e.preventDefault();
  };
  
  const handleMouseDown = (e: React.MouseEvent) => {
    e.stopPropagation();
    divRef.current = e.currentTarget;
    let { top, left } = divRef.current.style;
    console.info('top, left', top, left);
    // 如果直接修改属性,值的类型会变为字符串,所以要转为数值型
    const startTop = top ? Number(top.replace('px', '')) : 0;
    const startLeft = left ? Number(left.replace('px', '')) : 0;
    const startY = e.clientY;
    const startX = e.clientX;
    const move = (moveEvent: { clientX: number; clientY: number }) => {
      if (!divRef.current) return; // 检查divRef.current是否存在
      const currX = moveEvent.clientX;
      const currY = moveEvent.clientY;
      console.info('move', currX, currY);
      const newTop = currY - startY + startTop;
      const newLeft = currX - startX + startLeft;
      // 获取父元素的边界
      const parent = divRef.current.parentElement;
      if (!parent) return;
      const parentRect = parent.getBoundingClientRect();
      const divRect = divRef.current.getBoundingClientRect();
      // 限制div不超过父元素的边界
      const maxTop = parentRect.height - divRect.height;
      const maxLeft = parentRect.width - divRect.width;
      top = `${Math.min(Math.max(newTop, 0), maxTop)}px`;
      left = `${Math.min(Math.max(newLeft, 0), maxLeft)}px`;
      // 修改当前组件样式
      divRef.current.style.left = left;
      divRef.current.style.top = top;
    };
    const up = () => {
      document.removeEventListener('mousemove', move);
      document.removeEventListener('mouseup', up);
      divRef.current = null; // 清除对元素的引用
    };
    document.addEventListener('mousemove', move);
    document.addEventListener('mouseup', up);
  };
  return (
    
       handleDragStart(e, 1)}
        style={{
          width: '100px',
          height: '100px',
          backgroundColor: 'red',
          margin: '30px',
          cursor: 'pointer',
        }}
      >
        demo2
      
      {
          width: '300px',
          height: '300px',
          margin: '30px',
          backgroundColor: 'blue',
          position: 'relative',
        }}
      >
        content
        {demos.map((demo) => (
          {
              width: '100px',
              height: '100px',
              backgroundColor: 'red',
              cursor: 'pointer',
              position: 'absolute',
              left: `${demo.x}px`,
              top: `${demo.y}px`,
            }}
          >
            demo {demo.id}
          
        ))}
      
    
  );
};
export default App;
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon