【问题标题】:Why is my draggable component in React moving ahead of cursor onmousemove?为什么我在 React 中的可拖动组件在光标 onmousemove 之前移动?
【发布时间】:2021-07-31 04:57:43
【问题描述】:

这是我的第一个 Stack Overflow 问题,所以请耐心等待我,如果您需要更多信息,请告诉我!我实际上是在重新创建一个简化的 Beyond20 可交互地图,供 Dungeon Master 使用。为第一次初级开发应用构建项目组合。

无论如何,我已经用纯色背景色 div 制作了可移动的“片段”,它们带有短文本名称,可以在板上的地图图像周围移动。我不想导入像 React DnD 这样的预构建库,而是想从头开始这样做,以更好地了解机制。我将移动逻辑存储在组件 Draggable(如下)中。然而,每当我拖动“一块”时,该块会逐渐移动到光标前方(注意:它不会像我在其他地方读到的那样落后,它会沿着光标移动的任何方向缓慢向前滑动),并且会发生这种行为在我测试过的每个显示器屏幕上,除了我在上面编写代码的原始显示器。还要注意的是,在任何拖动事件中,可拖动组件都会从光标移动一段可复制的距离,这意味着,如果我拖动我的元素,比如 300 像素,它总是会在我的光标之前以相同的距离结束。

我希望这是有道理的。如果我能澄清任何事情,请告诉我。非常感谢任何和所有建议!

可拖动组件:

import React, { useState, useEffect, useRef } from 'react';


function Draggable({ 
  children, 
  position, 
  updatePosition, 
  deleteIcon, 
  id
 }) {
  const [drop, setDrop] = useState({ x: position.x, y: position.y })
  const dragRef = useRef()

  const handlePointerDown = (e) => {
    window.addEventListener('pointermove', handleDragMove);
    window.addEventListener('pointerup', handlePointerUp);
  };
  
  const handleDragMove = (e) => {
      dragRef.current.style.left = `${dragRef.current.offsetLeft + e.movementX}px`
      dragRef.current.style.top = `${dragRef.current.offsetTop + e.movementY}px`
  };

  const handlePointerUp = (e) => {

    const aspectBox = document.getElementById('aspectRatioBox')
    const bounding = dragRef.current.getBoundingClientRect();

    if(bounding.x < 100 && bounding.y < 100) {
      //Below conditional is for deleting an Icon if dropped within a specific area on page

      try {
        deleteIcon(id)
      } catch(exception) {
        console.log('Unable to delete icon', exception)
      }
    } else if (drop.x !== dragRef.current.style.left && drop.y !== dragRef.current.style.top) {  
      //This is for updating the position in the server through socket.io and saving to database

      setDrop({
        x: `${dragRef.current.style.left.replace(/px/g, '')/aspectBox.clientWidth*100}%`,
        y: `${dragRef.current.style.top.replace(/px/g, '')/aspectBox.clientHeight*100}%`
      })
    }
    window.removeEventListener('pointermove', handleDragMove);
    window.removeEventListener('pointerup', handlePointerUp);
  }



  const preventBehavior =(e) => {
    e.preventDefault();
  }

  useEffect(() => {
    window.addEventListener('touchmove', preventBehavior, {passive: false})

    return () => {
      window.removeEventListener('pointerup', handlePointerUp)
      window.removeEventListener('touchmove', preventBehavior, {passive: false})
      window.removeEventListener('pointermove', handleDragMove);
      window.removeEventListener('pointerup', handlePointerUp);
    } 

  }, [])


  const firstRender = useRef(true);
  useEffect(() => {
    if(!firstRender.current) {
      updatePosition({ 
        x: drop.x, 
        y: drop.y 
      }, id)
    }
  }, [drop.x, drop.y] ) 

  useEffect(() => { firstRender.current = false }, [])
  return (
    <div
      onPointerDown={handlePointerDown}
      style={{top: position.y, left: position.x}}
      className="draggableBox"
      ref={dragRef}
    >
      {children}
    </div>

  )
}

export default Draggable

【问题讨论】:

    标签: javascript reactjs events draggable drag


    【解决方案1】:

    因此,在 Google Foo 失败了很多小时后,我找到了解决问题的可靠方法。

    我不相信这解决了我的根本问题是可拖动元素领先于光标,但我相信这与我通过 e.movementX 和 e.movementY 更新位置的附加性质有关。

    const handlePointerDown = (e) => {
    
      const { left, top }  = dragRef.current.getBoundingClientRect()
      posRef.current = {
        x: left - e.clientX,
        y: top - e.clientY
      }
    
      
       window.addEventListener('pointermove', handleDragMove);
       window.addEventListener('pointerup', handlePointerUp);
    
       e.stopPropagation();
       e.preventDefault();
    };
      
    
    const handleDragMove = (e) => {
      const aspectBox = document.getElementById('aspectRatioBox').getBoundingClientRect()
    
      dragRef.current.style.left = `${(e.clientX + posRef.current.x - aspectBox.left)/aspectBox.width*100}%`
      dragRef.current.style.top = `${(e.clientY + posRef.current.y - aspectBox.top)/aspectBox.height*100}%`
     
      e.stopPropagation();
      e.preventDefault();
    
    
    };
    

    我通过它移动的框的增量和光标的 e.Client 位置来获得可拖动元素的相对位置。我在其中添加了一个 ref posRef,它允许更精确地移动图标,而不是立即将光标捕捉到图标的左上角。

    希望这对发现自己处于类似情况的人有所帮助!!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多