Reputation: 35
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";
});
Upvotes: 1
Views: 3001
Reputation: 49
I had to add the offset for the nextwork element, and reduce by the scroll to put the element in the correct location.
this.showAside(
properties.pointer.DOM.x + this.el.nativeElement.offsetLeft, properties.pointer.DOM.y + this.el.nativeElement.offsetTop - this.el.nativeElement.parentElement.parentElement.parentElement.scrollTop, this.nodes.find(_ => _.id == properties.node)
);
Upvotes: 0
Reputation: 31
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
Upvotes: 0
Reputation: 35
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.
Upvotes: 1
Reputation: 2093
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
Upvotes: 0