react-dnd:拖出一行

时间:2016-12-16 02:01:40

标签: reactjs typescript react-dnd

我正在构建一个允许用户使用拖放操作构建图形的组件。有一个节点可以拖出新节点,它们可以拖动画布周围的节点等。

现在,我需要允许它们通过从一个节点的输出拖动到下一个节点的输入端来创建边缘。严格来说,这不是拖放,因为可拖动停留,而是显示源自光标下的可拖动和填充的线,直到最终,当用户在将鼠标悬停在活动状态时释放时目标,边缘完成。

Drag-n-drop似乎几乎我想要的一切。它具有悬停信号,在拖动符合条件的Draggable时突出显示拖放目标,依此类推。有两件事我无法弄清楚该怎么做。一个是停止可拖动的移动。我可以通过放置元素的两个副本来欺骗它,一个在另一个下面,然后禁用拖动预览,但是如果有一个更好的简单标记。

另一个似乎更像是一个表演者。当我拖动时,收集功能不会连续发射事件(我知道,按设计)。我需要触发onMouseMove的东西来不断更新线。因为拖放确实做了我需要的一些东西,并且由于我已经承担了依赖它的尺寸成本,所以重复使用它会很棒。

我迄今为止最好的想法是在beginDrag上安装onMouseMove处理程序并清理endDrag上的行,在drop上建立任何新边缘。不幸的是,我认为有些事情正在阻止mousemove事件的传播,因为即使我在开始拖动时输入beginDrag,我的处理程序也不会触发。

     let mouseMoveHandler = (ev: JQueryMouseEventObject) => {
       console.log("Draw a line from ", node.position, " to ", { x: ev.clientX, y: ev.clientY });
     };
     console.log("Dragging");
     $("body").on("mousemove", mouseMoveHandler);
     return { id, node, mouseMoveHandler: mouseMoveHandler};
  },
  endDrag: ({id, node}, monitor: DragSourceMonitor) => {
    const item = monitor.getItem() as any;
    $("body").off("mousemove", item.mouseMoveHandler);
  }

1 个答案:

答案 0 :(得分:2)

我目前正在处理的项目涉及相同的事情(绘制图形,使用react-dnd连接边缘)并遇到同样的问题。但是我注意到你的假设是

  

我拖动

时,收集功能不会连续触发事件

不正确。起初我也这么认为,但后来我意识到显示结果的原因是因为我的"画布"渲染功能太重了。 我按照the directions关于如何优化我的反应渲染功能但将我的节点层和链接层分成单独的子组件来解决了这个问题,这些子组件只有在它们发生变化时才会重新渲染。这使我的主渲染功能更轻松。然后当我渲染我的"待定"链接。它跟着我的鼠标光标很漂亮,没有口吃/凹陷。

这是从渲染函数中重新编写的内容:

render() {
    /* 
    Don't do anything heavy in the rendering function (incl, nodelayer and link layer) - even a console.log.
    Otherwise the pending link render will b e choppy. 
    */
    const { renderPendingLink } = this;
    const { connectDropTarget } = this.props;
    const canvas = connectDropTarget(<div style={{ width: '100%', height: '1000px' }} ref={ref => this._canvasRef = ref}>
        <div style={{ position: 'absolute', width: '100%', height: '100%' }}>
            <NodesLayer nodes={this.nodesValuesArray} createLink={this.createLink} />
            <svg style={{ width: '100%', height: '100%' }}>
                <LinksLayer links={this.linksValuesArray} />
                {renderPendingLink()}
            </svg>
        </div>
    </div>)
    return (<div>
        <PanelToolboxWidget />
        {canvas}
    </div>)
}
}

renderPendingLink() {
    const { item, itemType, isDragging } = this.props;
    if (isDragging && itemType == ItemTypes.PORT) {
        const { port } = item;
        const { currentOffset } = this.props;
        if (!currentOffset | !this._canvasRef) {
            return null;
        }
        return (
            <PendingLinkWidget
                start={port.getPortCenterRelativeToCanvas}
                end={getLocalisedDropCoords(currentOffset, this._canvasRef)}
            />
        )
    }
    return null;
}

LinksLayerWidget看起来像这样(我使用mobX):

@observer class LinksLayer extends React.PureComponent {
render() {
    const { links } = this.props;
    return (<svg>
        {_.map(links, l => <LinkWidget link={l} key={l.uuid} />)}
    </svg>)
}

}

它对我有用,我希望它可以帮到你。