(Vis.js 网络)getPositions 的节点坐标不正确?

(Vis.js network) Incorrect node coordinates with getPositions?

在我的vis.js 网络 中,我想在单击节点时在该节点的位置出现一个弹出窗口。

我使用了getPositions方法,但是弹窗出现在错误的位置(左上角太多),好像坐标不正确。

network.on("click", function (params) {
        // Get the node ID
        var nodeId = params.nodes[0];
        if (nodeId) {

            // Get the node title to show in the popup
            var popup = this.body.nodes[nodeId].options.title;

            // Get the node coordinates
            var nodePosition = network.getPositions(nodeId);
            var nodeX = nodePosition[nodeId].x;
            var nodeY = nodePosition[nodeId].y;

            // Show the tooltip in a div
            document.getElementById('popup').innerHTML = popup;
            document.getElementById('popup').style.display = "block";
            // Place the div
            document.getElementById('popup').style.position = "absolute";
            document.getElementById('popup').style.top = nodeY+'px';
            document.getElementById('popup').style.left = nodeX+'px';

        }
    });
    // Empty and hide the div when click elsewhere
    network.on("deselectNode", function (params) {
        document.getElementById('popup').innerHTML = null;
        document.getElementById('popup').style.display = "none";
    });

您正在使用 network.getPositions(params.nodes[0]),但是由于在 canvas 上放大和缩小以及移动网络时节点可能会发生很大变化positions 与节点的真实位置不匹配。我不知道这是 visjs 中的错误还是有其他原因。文档说他们 return 节点在 canvas space 中的位置。但在您的示例中显然不是这种情况。

查看文档 [https://visjs.github.io/vis-network/docs/network/#Events] 点击事件参数包含:

{
    nodes: [Array of selected nodeIds],
    edges: [Array of selected edgeIds],
    event: [Object] original click event,
    pointer: {
        DOM: {x:pointer_x, y:pointer_y},     // << Try using this values
        canvas: {x:canvas_x, y:canvas_y}
    }
}

尝试使用 params.pointer.DOM 或 params.pointer.canvas 位置 X 和 Y 来定位您的弹出窗口。这应该是光标的位置。这将与节点的位置相同,因为您单击了它。

所以尝试这样的事情:

    document.getElementById('popup').style.top = params.pointer.DOM.y +'px';
    document.getElementById('popup').style.left = params.pointer.DOM.x +'px';

-- 未测试

我在 vis support section of github 上得到了一些帮助。 原来诀窍是使用 canvasToDOM().

以下是它如何应用于我的代码:

network.on("click", function(params) {
  // Get the node ID
  var nodeId = params.nodes[0];
  if (nodeId) {
    // Get the node title to show in the popup
    var popup = this.body.nodes[nodeId].options.title;

    // Get the node coordinates
    var { x: nodeX, y: nodeY } = network.canvasToDOM(
      network.getPositions([nodeId])[nodeId]
    );

    // Show the tooltip in a div
    document.getElementById("popup").style.display = "block";
    // Place the div
    document.getElementById("popup").style.position = "absolute";
    document.getElementById("popup").style.top = nodeY + "px";
    document.getElementById("popup").style.left = nodeX + "px";
  }
});

当网络保持不变时它可以工作,但在我的例子中我想适应网络并放大点击的节点,所以弹出窗口不会跟随,但由于这是一个单独的问题我会 post另一个问题。

使用点击事件并在 canvas 上绘制 div。

network.on("click", function(params) {
    // Get the node ID
    var nodeId = params.nodes[0];
    if (nodeId) {
        // Get the node title to show in the popup
        var popup = this.body.nodes[nodeId].options.title;

        //use JQUERY to see where the canvas is on the page.
        var canvasPosition = $('.vis-network').position();

        //the params give x & y relative to the edge of the canvas, not to the 
        //whole document.
        var clickX = params.pointer.DOM.x + canvasPosition.top;
        var clickY = params.pointer.DOM.y + canvasPosition.left;

        // Show the tooltip in a div
        document.getElementById("popup").style.display = "block";
        // Place the div
        document.getElementById("popup").style.position = "absolute";
        document.getElementById("popup").style.top = clickY + "px";
        document.getElementById("popup").style.left = clickX + "px";
    }
});

fixed position for tooltip/popup example