3

我正在构建一个组件,该组件允许用户通过拖放构建图形。有一个节点井,他们可以在其中拖出新节点,他们可以在画布周围拖动节点等。

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

拖放似乎可以完成我想要的几乎所有事情。它具有悬停信号,当符合条件的 Draggable 正在拖动时突出显示放置目标,等等。有两件事我不知道该怎么做。一是完全停止可拖动的移动。我可以通过放置元素的两个副本来欺骗它,一个在另一个下面,然后禁用拖动预览,但如果有一个简单的标志会更好。

另一个似乎更像是一个表演者。collect 函数不会在我拖动时连续触发事件(我知道,设计使然)。我需要一些能触发 onMouseMove 的东西来不断更新这条线。由于拖放确实做了一些我需要的东西,而且我已经承担了依赖它的大小成本,所以重用它会很棒。

到目前为止,我最好的想法是在 上安装一个 onMouseMove 处理程序beginDrag并清理线上,在 上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);
  }
4

1 回答 1

2

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

当我拖动时,收集功能不会连续触发事件

是不正确的。一开始我也这么认为,但后来我意识到显示卡顿的原因是因为我的“画布”渲染功能太重了。我通过遵循有关如何优化我的反应渲染功能的说明解决了这个问题,将我的节点层和链接层划分为单独的子组件,只有在它们发生变化时才会重新渲染。这使我的主要渲染功能更轻松。然后当我呈现我的“待处理”链接时。它完美地跟随我的鼠标光标,没有卡顿/卡顿。

这是从我的渲染函数中返回的内容:

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>)
}

}

它对我有用,我希望它对你有帮助。

于 2017-08-20T14:57:12.987 回答