简体   繁体   中英

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

In my vis.js network , I want to make a popup appear at the position of a node when I click on the node.

I used the getPositions method but the popup appears in the wrong place (too much on the left and top corner), as if the coordinates were incorrect.

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

You are using network.getPositions(params.nodes[0]), but since the nodes can change a lot when zooming in and out and moving the network on the canvas somehow the positions do not match the real position of the node. I do not know if this is a bug in visjs or there is some other reason for it. The docs say they return the position of the node in the canvas space. But thats clearly not the case in your example.

Looking at the docs [ https://visjs.github.io/vis-network/docs/network/#Events ] the click event argument contains:

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

Try to use the params.pointer.DOM or params.pointer.canvas positions X and Y to position your popup. This should be the location of the cursor. This will be the same position as the node, since you clicked on it.

So try something like:

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

-- Untested

I got some help on the vis support section of github . Turns out the trick was to use canvasToDOM() .

Here's how it applied to my code:

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

It works when the network stays put, but in my case I want to fit the network and zoom on the clicked node, so the popup doesn't follow, but since this is a separate issue I will post another question.

use the click event and paint a div over the canvas.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM