I am trying to retrieve the x, y position for the “g” element of the nodes. As provided in the screenshot a browser inspector gets the transform="translate(x,y)"
values and I want to return those in a console.log
too. To do so I added a .on("click", getPosition)
function and tried different approaches. Unfortunately the official D3.js API removed d3.transform without any replacement explanation.
What I am hoping to get from stackoverflow is a practical example, as I am lost.
Code snippet:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>D3v6 Pack</title> <script src="https://d3js.org/d3.v6.min.js"></script> </head> <style> body { background-color: #e6e7ee; } circle { fill: whitesmoke; stroke: black; stroke-width: 1px; } </style> <body> <script> var svg = d3.select("body").append("svg") .attr("width", window.innerWidth) .attr("height", window.innerHeight) .attr("class", "svg") .call(d3.zoom().on("zoom", function (event) { svg.attr("transform", event.transform) })) .append("g") var linkContainer = svg.append("g").attr("class", "linkContainer") var nodeContainer = svg.append("g").attr("class", "nodeContainer") var data = { "nodes": [ { "id": "A" }, { "id": "B" }, { "id": "C" }, { "id": "D" } ], "links": [ { "source": "B", "target": "A" }, { "source": "C", "target": "A" }, { "source": "D", "target": "A" } ] } var force = d3.forceSimulation() .force("link", d3.forceLink().id(function (d) { return d.id; }).distance(200)) .force("charge", d3.forceManyBody().strength(-650)) .force("center", d3.forceCenter(window.innerWidth / 2, window.innerHeight / 2)) .force("collision", d3.forceCollide().radius(50)) var links = linkContainer.selectAll(".link") .data(data.links) .join("line") .attr("class", "link") .style("stroke", "black") .style("opacity", 0.2) var nodes = nodeContainer.selectAll(".node") .data(data.nodes, function (d) { return d.id; }) .enter() .append("g") .attr("class", "node") .attr("id", function (d) { return d.id; }) .on("click", getPosition) .call(d3.drag() .on("start", dragStarted) .on("drag", dragged) .on("end", dragEnded) ) nodes .append("circle") .attr("r", 40); force .nodes(data.nodes) .on("tick", tick) force .force("link") .links(data.links) function getPosition(event, d) { var xPos = "xPos from any node" //var xPos = this.x //var xPos = d3.select("#A").svg.x //var xPos = d3.select("#A").transfor.x //var xPos = d3.select("#A").transform.translate[0] //var xPos = d3.select("#A").translate[0] //var xPos = d3.select("#A").x console.log(xPos) } function tick() { links .attr("x1", function (d) { return d.source.x; }) .attr("y1", function (d) { return d.source.y; }) .attr("x2", function (d) { return d.target.x; }) .attr("y2", function (d) { return d.target.y; }); nodes.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; }); } function dragStarted(event, d) { if (!event.active) force.alphaTarget(0.3).restart(); d.fx = d.x; d.fy = d.y; } function dragged(event, d) { d.fx = event.x; d.fy = event.y; } function dragEnded(event, d) { if (!event.active) force.alphaTarget(0); d.fx = undefined; d.fy = undefined; } </script> </body> </html>
Advertisement
Answer
This code works:
function getPosition(event, d) { const element = d3.select(this); const val = element.attr('transform').split(/[s,()]+/); const x = parseFloat(val[1]); const y = parseFloat(val[2]); console.log(x, y) }
You can see it in a fiddle