使用js鼠标(mouse)事件实现拖放html元素

2021-08-09  本文已影响0人  mudssky

还是一个用react编写的toc组件的例子

我们把toc组件设置成fix定位,然后改变元素的style的left和top值,就能再页面上随意移动元素了.

为什么不用drag事件?

drag事件是html5新添加的api,所以它的兼容性会更差一些.

另外drag事件也不是很好用, 和我现在想要实现的功能差挺多的,而且复杂度反而更高.

下面是drag相关的6个事件,

drag是包含两个物体,从一个元素拖动进入另一个元素,

针对对象 事件名称 说明
被拖动的元素 dragstart 在元素开始被拖动时候触发
drag 在元素被拖动时反复触发
dragend 在拖动操作完成时触发
目的地对象 dragenter 当被拖动元素进入目的地元素所占据的屏幕空间时触发
dragover 当被拖动元素在目的地元素内时触发
dragleave 当被拖动元素没有放下就离开目的地元素时触发

而我目前的需求,只会使用到被拖动的元素本身.

所以并不适合用drag的api.

使用mouse 鼠标事件实现拖放

mouse事件相比drag更加底层,能实现更精细的控制.

下面是这个react组件,拖放事件的代码.

其中需要注意的是,

下面这行代码是必要的,因为浏览器自己的拖放处理和我们的拖放处理会产生冲突,我们用return false可以禁止默认行为.

tocEl.current.ondragstart = function () {
        return false
      }
 // 添加拖拽组件位置的监听
  useEffect(() => {
    //   组件生成时,从localStorage获取过去使用的位置
    const jsonstr = localStorage.getItem('tocposition')
    let startPostion = { left: 20, top: 50 }
    if (jsonstr) {
      startPostion = JSON.parse(jsonstr)
    }
    let tocPosition = startPostion
    function moveAt(tocPosition: { left: number; top: number }) {
      tocEl.current!.style.left = tocPosition.left + 'px'
      tocEl.current!.style.top = tocPosition.top + 'px'
    }
    moveAt(tocPosition)
    if (tocEl.current) {
      // console.log(tocEl)

      const onMouseDown = function (event: MouseEvent) {
        // 按下鼠标时,我们可以记住鼠标按下的位置相对于拖动地节点左上角的距离
        const shiftX =
          event.clientX - (tocEl.current?.getBoundingClientRect().left || 0)
        const shiftY =
          event.clientY - (tocEl.current?.getBoundingClientRect().top || 0)

        // 按下鼠标后,添加移动事件和鼠标放下的事件
        function onMouseMove(event: MouseEvent) {
          // console.log(event.pageX, event.pageY, event.clientX, event.clientY)
          tocPosition = {
            left: event.clientX - shiftX,
            top: event.clientY - shiftY,
          }
          moveAt(tocPosition)
        }
        document.addEventListener('mousemove', onMouseMove)
        function onMouseUp(event: MouseEvent) {
          // 放下后移除事件
          document.removeEventListener('mousemove', onMouseMove)
          document.removeEventListener('mouseup', onMouseUp)
          localStorage.setItem('tocposition', JSON.stringify(tocPosition))
        }
        document.addEventListener('mouseup', onMouseUp)
      }
      tocEl.current.addEventListener('mousedown', onMouseDown)

      tocEl.current.ondragstart = function () {
        return false
      }
    }
    return () => {
      //   cleanup
    }
  }, [])
上一篇下一篇

猜你喜欢

热点阅读