【问题标题】:React DND - get coordinates of dragged element as the mouse movesReact DND - 在鼠标移动时获取拖动元素的坐标
【发布时间】:2019-04-16 12:14:04
【问题描述】:

我有一个图像,当我拖动时我也想实现旋转。我想到的解决方案是使用 React DnD 来获取拖动图像位置的 xy 坐标并计算原始图像位置之间的差异。这种差异的值将构成进行旋转的基础。

我查看了 ReactDnD 库中的示例,发现 DragSource 规范可以访问 Monitor 变量。这个监视器变量可以访问像getInitialClientOffset() 这样的方法。当我实现这个值的console.log() 时,它会显示我释放鼠标时的最后一个坐标集。

使用这个库,有没有一种简单的方法可以在我移动鼠标时获取被拖动元素的当前位置?

import React from 'react'
import { DragSource } from 'react-dnd'

// Drag sources and drop targets only interact
// if they have the same string type.
// You want to keep types in a separate file with
// the rest of your app's constants.
const Types = {
  CARD: 'card',
}

/**
 * Specifies the drag source contract.
 * Only `beginDrag` function is required.
 */
const cardSource = {
  beginDrag(props,monitor,component) {
    // Return the data describing the dragged item
    const clientOffset = monitor.getSourceClientOffset();
    const item = { id: props.id }
    console.log(clientOffset);
    return item
  },

  isDragging(props, monitor){
    console.log(monitor.getClientOffset())
  },

  endDrag(props, monitor, component) {
    if (!monitor.didDrop()) {
      return
    }

    // When dropped on a compatible target, do something
    const item = monitor.getItem()
    const dropResult = monitor.getDropResult()
    console.log(item,dropResult)
    //CardActions.moveCardToList(item.id, dropResult.listId)
  },
}

/**
 * Specifies which props to inject into your component.
 */
function collect(connect, monitor) {
  return {
    // Call this function inside render()
    // to let React DnD handle the drag events:
    connectDragSource: connect.dragSource(),
    // You can ask the monitor about the current drag state:
    isDragging: monitor.isDragging(),
  }
}

function Card(props) {
  // Your component receives its own props as usual
  const { id } = props

  // These two props are injected by React DnD,
  // as defined by your `collect` function above:
  const { isDragging, connectDragSource } = props



  return connectDragSource(
    <div>
      I am a draggable card number {id}
      {isDragging && ' (and I am being dragged now)'}
    </div>,
  )
}

// Export the wrapped version
export default DragSource(Types.CARD, cardSource, collect)(Card)

【问题讨论】:

    标签: javascript reactjs react-dnd


    【解决方案1】:

    据我所知,自定义拖动层存在严重的性能问题。最好直接订阅底层API(官方文档严重缺失,但可以通过阅读drag layer源码获取):

    const dragDropManager = useDragDropManager();
    const monitor = dragDropManager.getMonitor();
    
    React.useEffect(() => monitor.subscribeToOffsetChange(() => {
      const offset = monitor.getClientOffset();
      // do stuff like setState, though consider directly updating style through refs for performance
    }), [monitor]);
    

    您还可以使用一些基于拖动状态的标志来仅在需要时订阅(简单的isDragging &amp;&amp; monitor.subscribe... 加上依赖项数组就可以了)。

    【讨论】:

      【解决方案2】:

      useDrop 钩子有一个 hover(item, monitor) 方法,可以满足您的需求。当您将鼠标悬停在放置目标上时,它会反复触发。

      【讨论】:

        【解决方案3】:

        我在事后以这种方式发布,但如果有人正在寻找这个答案,那么 react-dnd 的做法是使用他们所谓的拖动层 - 它为您提供了一种使用自定义的方法拖动时要显示的组件。

        他们在这里有一个完整的例子: https://codesandbox.io/s/github/react-dnd/react-dnd/tree/gh-pages/examples_hooks_js/02-drag-around/custom-drag-layer?from-embed=&file=/src/CustomDragLayer.jsx

        您也可以在文档中查看 useDragLayer 和 DragLayerMonitor

        【讨论】:

          【解决方案4】:

          你可以使用

          ReactDOM.findDOMNode(component).getBoundingClientRect();
          

          参考:https://reactjs.org/docs/react-dom.html#finddomnode

          或者只是将a ref 设置为您的组件实例,然后在onmousemove 事件中的实例上获取getBoundingClientRect()

          【讨论】:

          • 您能否详细说明一个示例或链接到一个在线示例?
          • 当然,搜索“getBoundingClientRect() React”会得到很多结果,如:medium.com/@chung.andrew7/…
          【解决方案5】:

          据我所知,您需要通过 HTML5Backend 获得当前拖动元素的所有偏移量,但如果您使用 MouseBackend,您可以轻松获得坐标 https://github.com/zyzo/react-dnd-mouse-backend

          查看预览示例

          【讨论】:

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