Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.4k views
in Technique[技术] by (71.8m points)

react实现div拖拽功能无效果

代码如下,拖拽总共分为onMouseDown、onMouseMove、onMouseUp三个事件,运行后div无法拖拽。

import React, {useState} from "react";

const Drag:React.FC=(props)=>{

    const [pageX,setpageX] = useState<any>('1000px')
    const [pageY,setpageY] = useState<any>('500px')
    const [diffX,setdiffX] = useState<any>('')  
    const [diffY,setdiffY] = useState<any>('')
    const [moving,setMoving] = useState<boolean>(false)

    // 获取鼠标点击对象时的坐标、对象的坐标以及两者的位移
    const getPosition =(e:any)=> {
        //需要移动的元素
        let dragdom:any = document.getElementById('drag')

        //由于Y轴出现滚动条,需要与鼠标保持一致,存储页面相对位置
        const X = dragdom.offsetLeft       
        const Y = dragdom.offsetTop

        console.log(X);
        console.log(Y);

        // 获取鼠标在页面中的位置
        let mouseX = e.pageX
        let mouseY = e.pageY
        
        // 鼠标点击位置与对象的位移,也就是鼠标按下时在盒子中的位置
        const diffX = mouseX - X
        const diffY = mouseY - Y
        return {X, Y, mouseX, mouseY, diffX, diffY}
    }

   /**
   * 鼠标按下,设置div状态为可移动,并注册鼠标移动事件
   * 计算鼠标按下时,指针所在位置与div位置以及两者的差值
   **/
  const onMouseDown =(e:any)=> {
    const position = getPosition(e)
    document.onmousemove = onMouseMove
    document.onmouseup = onMouseUp
    setdiffX(position.diffX)
    setdiffY(position.diffY)
    setMoving(true)
  }

  // 松开鼠标,设置div状态为不可移动
  const onMouseUp =(e:any)=> {
    moving && setMoving(false);
  }

    // 鼠标移动重新设置div的位置
    const onMouseMove =(e:any)=> {
        if (moving) {
          // 获取鼠标位置数据
          const position = getPosition(e)
          // 计算div应该随鼠标移动到的坐标
          const x = position.mouseX - diffX
          const y = position.mouseY - diffY
          // 窗口大小,结构限制,需要做调整,减去侧边栏宽度
          const { clientWidth, clientHeight } = document.documentElement
          const modal:any = document.getElementById('drag')
          if (modal) {
            // 计算div坐标的最大值
            const maxHeight = clientHeight - modal.offsetHeight
            const maxWidth = clientWidth - modal.offsetWidth
            // 判断得出div的最终位置,不得超出浏览器可见窗口
            const left = x > 0 ? (x < maxWidth ? x : maxWidth) : 0
            const top = y > 0 ? (y < maxHeight ? y : maxHeight) : 0
            setpageX(left)
            setpageY(top)
          }
        }
      }


    const newStyle:any = {
        width:'70px',
        height:'70px',
        boxSizing: 'border-box',
        position: 'absolute',
        top: pageY,
        left: pageX,
        zIndex: 999,
        backgroundColor: '#7d7979d9',
    
    }

    return (
        <>
        <div id='drag' style={newStyle} onMouseDown={onMouseDown}></div>
        </>
    )
}
export default Drag

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

最主要的问题就是useState的滥用,除了pageY和pageX,其他的都没必要使用useState,特别是moving,因为useState是异步的,所以当你用setMoving设置moving,其实他的值并没有立刻改变,所以在onMouseMove中,他走不到下面的代码。还有一些小问题,比如onMouseMove和onMouseUp覆盖了document原本的事件,这个可以在onMouseDown中保存一份,在onMouseUp中再给他还原,其他的类似元素本身有动画怎么处理,元素拖拽越界怎么处理,浏览器兼容性等就不说了。


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...