【问题标题】:react-dnd: drag out a linereact-dnd:拖出一行
【发布时间】:2017-05-01 18:23:22
【问题描述】:

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

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

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

另一个似乎更像是一个表演者。 collect 函数不会在我拖动时连续触发事件(我知道,设计使然)。我需要一些能触发 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);
  }

【问题讨论】:

    标签: reactjs typescript react-dnd


    【解决方案1】:

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

    collect 函数不会在我拖动时连续触发事件

    不正确。一开始我也是这么想的,但后来我意识到显示卡顿的原因是因为我的“画布”渲染功能太重了。 我通过关注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>)
    }
    

    }

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

    【讨论】:

    • 你能分享你的例子吗?
    猜你喜欢
    • 2020-05-05
    • 1970-01-01
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    • 1970-01-01
    • 2021-04-15
    • 1970-01-01
    相关资源
    最近更新 更多