javascriptpopupvis.jsvis.js-network

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

Solution

  • 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.